Merge all changes from the libaegisub branch into trunk, the effective range is r4175:4330. All options have been re-done and now use Cajun to support a json-backed format.

Initial support for low-level access and file I/O methods are included as well.

Originally committed to SVN as r4331.
This commit is contained in:
Amar Takhar 2010-05-21 01:13:36 +00:00
parent 23972b10bc
commit 40e12403d5
141 changed files with 6681 additions and 2960 deletions

View file

@ -14,6 +14,7 @@ ffmpegsource = libffms
endif
SUBDIRS = \
libaegisub \
$(ffmpegsource) \
$(libass) \
$(univchardet) \

View file

@ -22,7 +22,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_debug32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops"
InheritedPropertySheets=".\suffix_debug32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
>
<Tool
@ -88,7 +88,7 @@
<Configuration
Name="Debug|x64"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_debug64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops"
InheritedPropertySheets=".\suffix_debug64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
>
<Tool
@ -154,7 +154,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_release32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops"
InheritedPropertySheets=".\suffix_release32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
@ -223,7 +223,7 @@
<Configuration
Name="Release|x64"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_release64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops"
InheritedPropertySheets=".\suffix_release64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
@ -1103,14 +1103,6 @@
RelativePath="..\..\src\dialog_kara_timing_copy.h"
>
</File>
<File
RelativePath="..\..\src\dialog_options.cpp"
>
</File>
<File
RelativePath="..\..\src\dialog_options.h"
>
</File>
<File
RelativePath="..\..\src\dialog_paste_over.cpp"
>
@ -1255,10 +1247,62 @@
RelativePath="..\..\src\dialog_video_details.h"
>
</File>
<File
RelativePath="..\..\src\preferences.cpp"
>
</File>
</Filter>
<Filter
Name="Core"
>
<File
RelativePath="..\..\src\agi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\agi_pre.h"
>
</File>
<File
RelativePath="..\..\src\compat.cpp"
>
</File>
<File
RelativePath="..\..\src\compat.h"
>
</File>
<File
RelativePath="..\..\src\frame_main.cpp"
>
@ -1307,46 +1351,6 @@
RelativePath="..\..\src\setup.cpp"
>
</File>
<File
RelativePath="..\..\src\agi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\agi_pre.h"
>
</File>
<File
RelativePath="..\..\src\subs_edit_box.cpp"
>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="libaegisub_include_dir"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\libaegisub\include&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="compiler_options"
>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
OpenMP="true"
WarningLevel="3"
WarnAsError="true"
DebugInformationFormat="3"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateManifest="true"
GenerateDebugInformation="true"
SubSystem="2"
LargeAddressAware="2"
DataExecutionPrevention="2"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="compiler_options_debug"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
InlineFunctionExpansion="0"
EnableIntrinsicFunctions="false"
WholeProgramOptimization="false"
PreprocessorDefinitions="DEBUG;_DEBUG;_CRT_SECURE_NO_WARNINGS"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
DebugInformationFormat="4"
EnablePREfast="true"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
RandomizedBaseAddress="1"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libaegisub_vs2008"
ProjectGUID="{8732F2B6-B3C6-4AE8-986A-2A334E33334B}"
RootNamespace="libaegisub_vs2008"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options_debug.vsprops;..\aegisub_vs2008\wxlib_lib32.vsprops;..\aegisub_vs2008\suffix_debug32.vsprops;.\precomp_header.vsprops;.\src_msvc_include_dir.vsprops"
CharacterSet="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options.vsprops;..\aegisub_vs2008\wxlib_lib32.vsprops;..\aegisub_vs2008\suffix_release32.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
<Configuration
Name="Debug|x64"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options_debug.vsprops;..\aegisub_vs2008\wxlib_lib64.vsprops;..\aegisub_vs2008\suffix_debug64.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
<Configuration
Name="Release|x64"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options.vsprops;..\aegisub_vs2008\wxlib_lib64.vsprops;..\aegisub_vs2008\suffix_release64.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Common"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\libaegisub\common\mru.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option_visit.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option_visit.h"
>
</File>
<File
RelativePath="..\..\libaegisub\common\validator.cpp"
>
</File>
</Filter>
<Filter
Name="Windows"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\libaegisub\windows\access.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\windows\io.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\windows\lagi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\libaegisub\windows\util.cpp"
>
</File>
</Filter>
<Filter
Name="Include"
>
<File
RelativePath="..\..\libaegisub\include\libaegisub\access.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\colour.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\exception.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\io.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\mru.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\option.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\option_value.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\util.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\validator.h"
>
</File>
</Filter>
<File
RelativePath="..\..\libaegisub\lagi_pre.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="standard_outdirs"
OutputDirectory="$(SolutionDir)build/$(ProjectName)/$(PlatformName)/$(ConfigurationName)/"
IntermediateDirectory="$(OutDir)"
>
<Tool
Name="VCLibrarianTool"
OutputFile="$(LibraryOutDir)/$(ProjectName).lib"
/>
<Tool
Name="VCLinkerTool"
OutputFile=""
AdditionalLibraryDirectories="$(LibraryOutDir)"
ImportLibrary="$(LibraryOutDir)$(TargetName).lib"
/>
<UserMacro
Name="LibraryOutDir"
Value="$(SolutionDir)lib/$(PlatformName)/$(ConfigurationName)/"
/>
<UserMacro
Name="ExecutableOutDir"
Value="$(SolutionDir)bin/"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="precomp_header"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="../../libaegisub/lagi_pre.h"
ForcedIncludeFiles="../../libaegisub/lagi_pre.h"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="src_msvc_include_dir"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\src\msvc&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="wxlib_include"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(SolutionDir)/wxlib/include/&quot;;&quot;$(ProjectDir)../../libaegisub/include/&quot;"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="&quot;$(SolutionDir)/wxlib/include/&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -1204,6 +1204,7 @@ AC_CONFIG_FILES([
Makefile
automation/Makefile
desktop/Makefile
libaegisub/Makefile
libass/Makefile
libffms/Makefile
po/Makefile.in
@ -1214,6 +1215,7 @@ src/libosxutil/Makefile
src/libresrc/Makefile
tools/Makefile
universalchardet/Makefile
tests/Makefile
])
# Files that need substitution.

View file

@ -0,0 +1,12 @@
@INCLUDE = doxyfile_base
PROJECT_NAME = "libaegisub"
INPUT = ../../libaegisub/ ./pages_libaegisub
EXCLUDE_PATTERNS = */.svn* */.deps* */.libs*
PREDEFINED += \
__WINDOWS__ \
__UNIX__ \
__OSX__

View file

@ -17,6 +17,9 @@ case "$1" in
"reporter")
TRIM="${SRC_PWD}/reporter/"
;;
"libaegisub")
TRIM="${SRC_PWD}/libaegisub/"
;;
esac
export OUTPUT_DIR="$2"

View file

@ -0,0 +1,7 @@
/**
@defgroup base Base
@defgroup unix Unix
@defgroup windows Windows
@defgroup osx OS X
@defgroup io File I/O
*/

View file

@ -0,0 +1,11 @@
/** @mainpage
Main
- @ref base
Library
- @ref unix
- @ref windows
- @ref osx
- @ref io
*/

View file

@ -0,0 +1,5 @@
/** @page License libaegisub License
@verbinclude "LICENCE"
*/

View file

@ -0,0 +1,32 @@
# $Id$
AUTOMAKE_OPTIONS = subdir-objects
AM_CXXFLAGS=
DISTCLEANFILES=
lib_LTLIBRARIES = libaegisub-2.2.la
libaegisub_2_2_la_CPPFLAGS = -I../src/include -Iinclude -I. @WX_CPPFLAGS@
if PRECOMPILED_HEADER
BUILT_SOURCES = lagi_pre.h.gch
AM_CXXFLAGS += -include lagi_pre.h -Winvalid-pch -fpch-deps -fpch-preprocess
nodist_libaegisub_2_2_la_SOURCES = lagi_pre.h.gch
endif
if PRECOMPILED_HEADER
# This doesn't depend on Makefile on purpose, you should already know what you're doing when using this.
lagi_pre.h.gch: lagi_pre.h
@CXX@ $(libaegisub_2_2_la_CPPFLAGS) @CXXFLAGS@ @DEBUG_FLAGS@ -fPIC -DPIC lagi_pre.h
DISTCLEANFILES += lagi_pre.h.gch
endif
libaegisub_2_2_la_SOURCES = \
common/mru.cpp \
common/option.cpp \
common/option_visit.cpp \
common/validator.cpp \
unix/util.cpp \
unix/io.cpp \
unix/access.cpp
noinst_HEADERS = *.h

View file

@ -0,0 +1,203 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file mru.cpp
/// @brief Most Recently Used (MRU) Lists
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <time.h>
#endif
#include "libaegisub/access.h"
#include "libaegisub/mru.h"
#include "libaegisub/io.h"
namespace agi {
MRUManager::MRUManager(const std::string &config, const std::string &default_config): config_name(config) {
json::UnknownElement root;
std::istream *stream;
try {
stream = io::Open(config);
} catch (const acs::AcsNotFound&) {
stream = new std::istringstream(default_config);
}
try {
json::Reader::Read(root, *stream);
} catch (const json::Exception&) {
/// @todo Do something better here, maybe print the exact error
// std::cout << "json::Exception: " << e.what() << std::endl;
stream = new std::istringstream(default_config);
json::Reader::Read(root, *stream);
}
const json::Object& root_new = (json::Object)root;
json::Object::const_iterator index_object(root_new.Begin()), index_objectEnd(root_new.End());
for (; index_object != index_objectEnd; ++index_object) {
const json::Object::Member& member = *index_object;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
Load(member_name, (json::Array)element);
}
delete stream;
}
MRUManager::~MRUManager() {
Flush();
}
void MRUManager::Add(const std::string &key, const std::string &entry) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
MRUListMap &map = *index->second;
// Remove the file before adding it.
Remove(key, entry);
map.insert(std::pair<time_t, std::string>(time(NULL), entry));
Prune(map);
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
void MRUManager::Remove(const std::string &key, const std::string &entry) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
MRUListMap map = *index->second;
for (MRUListMap::iterator map_idx = map.begin(); map_idx != map.end();) {
if (map_idx->second == entry)
map.erase(map_idx++);
else
++map_idx;
}
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
const MRUManager::MRUListMap* MRUManager::Get(const std::string &key) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
return index->second;
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
const std::string MRUManager::GetEntry(const std::string &key, const int entry) {
const MRUManager::MRUListMap *map = Get(key);
MRUListMap::const_iterator index = map->begin();;
if ((unsigned int)entry > map->size())
throw MRUErrorIndexOutOfRange("Requested element index is out of range.");
std::advance(index, entry);
return index->second;
}
void MRUManager::Flush() {
json::Object out;
for (MRUMap::const_iterator i = mru.begin(); i != mru.end(); ++i) {
json::Array array;
MRUListMap *map_list = i->second;
for (MRUListMap::const_iterator i_lst = map_list->begin(); i_lst != map_list->end(); ++i_lst) {
json::Object obj;
obj["time"] = json::Number((double)i_lst->first);
obj["entry"] = json::String(i_lst->second);
array.Insert(obj);
}
out[i->first] = array;
}
io::Save file(config_name);
std::ofstream& ofp = file.Get();
json::Writer::Write(out, ofp);
}
/// @brief Prune MRUListMap to the desired length.
/// This uses the user-set values for MRU list length.
inline void MRUManager::Prune(MRUListMap& map) {
unsigned int size = 16;
MRUListMap::iterator index = map.begin();;
if (map.size() >= size) {
std::advance(index, size);
// Use a range incase the storage number shrinks.
map.erase(index, map.end());
}
}
/// @brief Load MRU Lists.
/// @param key List name.
/// @param array json::Array of values.
void MRUManager::Load(const std::string &key, const json::Array& array) {
json::Array::const_iterator index(array.Begin()), indexEnd(array.End());
MRUListMap *map = new MRUListMap();
for (; index != indexEnd; ++index) {
const json::Object& obj = *index;
time_t time = (time_t)(json::Number)obj["time"];
std::string entry = (json::String)obj["entry"];
map->insert(std::pair<time_t, std::string>(time, entry));
}
mru.insert(std::pair<std::string, MRUListMap*>(key, map));
Prune(*map);
}
}

View file

@ -0,0 +1,237 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file option.cpp
/// @brief Option interface.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <sstream>
#include <map>
#endif
#include "libaegisub/io.h"
#include "option_visit.h"
namespace agi {
Options::Options(const std::string &file, const std::string& default_config):
config_file(file), config_default(default_config), config_loaded(false) {
std::istringstream stream(default_config);
LoadConfig(stream);
}
Options::~Options() {
Flush();
}
void Options::ConfigNext(std::istream& stream) {
LoadConfig(stream);
}
void Options::ConfigUser() {
std::istream *stream = agi::io::Open(config_file);
LoadConfig(*stream);
config_loaded = true;
delete stream;
}
void Options::LoadConfig(std::istream& stream) {
/// @todo Store all previously loaded configs in an array for bug report purposes,
/// this is just a temp stub.
json::UnknownElement config_root;
try {
json::Reader::Read(config_root, stream);
} catch (json::Reader::ParseException& e) {
std::cout << "json::ParseException: " << e.what() << ", Line/offset: " << e.m_locTokenBegin.m_nLine + 1 << '/' << e.m_locTokenBegin.m_nLineOffset + 1 << std::endl << std::endl;
} catch (json::Exception& e) {
/// @todo Do something better here, maybe print the exact error
std::cout << "json::Exception: " << e.what() << std::endl;
}
ConfigVisitor config_visitor(values, std::string(""));
config_root.Accept(config_visitor);
}
OptionValue* Options::Get(const std::string &name) {
OptionValueMap::iterator index;
if ((index = values.find(name)) != values.end())
return index->second;
std::cout << "agi::Options::Get Option not found: (" << name << ")" << std::endl;
throw OptionErrorNotFound("Option value not found");
}
void Options::Flush() {
json::Object obj_out;
bool ok;
for (OptionValueMap::const_iterator i = values.begin(); i != values.end(); ++i) {
std::string key = i->first.substr(i->first.rfind("/")+1, i->first.size());
int type = i->second->GetType();
switch (type) {
case OptionValue::Type_String: {
ok = PutOption(obj_out, i->first, (json::String)i->second->GetString());
}
break;
case OptionValue::Type_Int:
ok = PutOption(obj_out, i->first, (json::Number)(const double)i->second->GetInt());
break;
case OptionValue::Type_Double:
ok = PutOption(obj_out, i->first, (json::Number)i->second->GetDouble());
break;
case OptionValue::Type_Colour: {
std::string str = std::string(i->second->GetColour());
ok = PutOption(obj_out, i->first, (json::String)str);
}
break;
case OptionValue::Type_Bool:
ok = PutOption(obj_out, i->first, (json::Boolean)i->second->GetBool());
break;
case OptionValue::Type_List_String: {
std::vector<std::string> array_string;
i->second->GetListString(array_string);
json::Array array;
for (std::vector<std::string>::const_iterator i_str = array_string.begin(); i_str != array_string.end(); ++i_str) {
json::Object obj;
obj["string"] = json::String(*i_str);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Int: {
std::vector<int64_t> array_int;
i->second->GetListInt(array_int);
json::Array array;
for (std::vector<int64_t>::const_iterator i_int = array_int.begin(); i_int != array_int.end(); ++i_int) {
json::Object obj;
obj["int"] = json::Number((const double)*i_int);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Double: {
std::vector<double> array_double;
i->second->GetListDouble(array_double);
json::Array array;
for (std::vector<double>::const_iterator i_double = array_double.begin(); i_double != array_double.end(); ++i_double) {
json::Object obj;
obj["double"] = json::Number(*i_double);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Colour: {
std::vector<Colour> array_colour;
i->second->GetListColour(array_colour);
json::Array array;
for (std::vector<Colour>::const_iterator i_colour = array_colour.begin(); i_colour != array_colour.end(); ++i_colour) {
json::Object obj;
Colour col = *i_colour;
std::string str = std::string(col);
obj["colour"] = json::String(str);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Bool: {
std::vector<bool> array_bool;
json::Array array;
i->second->GetListBool(array_bool);
for (std::vector<bool>::const_iterator i_bool = array_bool.begin(); i_bool != array_bool.end(); ++i_bool) {
json::Object obj;
obj["bool"] = json::Boolean(*i_bool);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
}
}
io::Save file(config_file);
json::Writer::Write(obj_out, file.Get());
}
bool Options::PutOption(json::Object &obj, const std::string &path, const json::UnknownElement &value) {
// Having a '/' denotes it is a leaf.
if (path.find('/') == std::string::npos) {
json::Object::iterator pos = obj.Find(path);
// Fail if a key of the same name already exists.
if (pos != obj.End())
throw OptionErrorDuplicateKey("Key already exists");
obj.Insert(json::Object::Member(path, value));
return true;
} else {
std::string thispart = path.substr(0, path.find("/"));
std::string restpart = path.substr(path.find("/")+1, path.size());
json::Object::iterator pos = obj.Find(thispart);
// New key, make object.
if (pos == obj.End())
pos = obj.Insert(json::Object::Member(thispart, json::Object()));
PutOptionVisitor visitor(restpart, value);
pos->element.Accept(visitor);
return visitor.result;
}
}
} // namespace agi

View file

@ -0,0 +1,242 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file option_visit.cpp
/// @brief Cajun JSON visitor to load config values.
/// @see option_visit.h
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <math.h>
#include <wx/colour.h>
#include <wx/wxcrtvararg.h>
#endif
#include <libaegisub/colour.h>
#include "option_visit.h"
namespace agi {
ConfigVisitor::ConfigVisitor(OptionValueMap &val, const std::string &member_name): values(val) {
// Corropsonding code is in AddOptionValue()
name = member_name + "/";
}
ConfigVisitor::~ConfigVisitor() {
}
void ConfigVisitor::Visit(const json::Object& object) {
json::Object::const_iterator index(object.Begin()), index_end(object.End());
for (; index != index_end; ++index) {
const json::Object::Member& member = *index;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
ConfigVisitor config_visitor(values, name + member_name);
element.Accept(config_visitor);
}
}
void ConfigVisitor::Visit(const json::Array& array) {
int init = 0;
OptionValueList *array_list;
json::Array::const_iterator index(array.Begin()), indexEnd(array.End());
for (; index != indexEnd; ++index) {
const json::Object& index_array = *index;
json::Object::const_iterator index_object(index_array.Begin()), index_objectEnd(index_array.End());
for (; index_object != index_objectEnd; ++index_object) {
const json::Object::Member& member = *index_object;
const std::string& member_name = member.name;
// This can only happen once since a list must always be of the same
// type, if we try inserting another type into it we want it to fail.
if (!init) {
if (member_name == "string") {
array_list = new OptionValueListString(name);
} else if (member_name == "int") {
array_list = new OptionValueListInt(name);
} else if (member_name == "double") {
array_list = new OptionValueListDouble(name);
} else if (member_name == "bool") {
array_list = new OptionValueListBool(name);
} else if (member_name == "colour") {
array_list = new OptionValueListColour(name);
} else {
throw OptionJsonValueArray("Array type not handled");
}
init = 1;
}
try {
if (member_name == "string") {
std::string val = (json::String)member.element;
array_list->InsertString(val);
} else if (member_name == "int") {
int64_t val = (int64_t)(json::Number)member.element;
array_list->InsertInt(val);
} else if (member_name == "double") {
double val = (json::Number)member.element;
array_list->InsertDouble(val);
} else if (member_name == "bool") {
bool val = (json::Boolean)member.element;
array_list->InsertBool(val);
} else if (member_name == "colour") {
std::string val = (json::String)member.element;
Colour col(val);
array_list->InsertColour(col);
}
AddOptionValue(array_list);
} catch (agi::Exception&) {
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
}
} // for index_object
} // for index
}
void ConfigVisitor::Visit(const json::Number& number) {
double val = number.Value();
if (int64_t(val) == ceil(val)) {
OptionValue *opt = new OptionValueInt(name, int64_t(val));
AddOptionValue(opt);
} else {
OptionValue *opt = new OptionValueDouble(name, val);
AddOptionValue(opt);
}
}
void ConfigVisitor::Visit(const json::String& string) {
OptionValue *opt;
if (string.Value().find("rgb(") == 0) {
opt = new OptionValueColour(name, string.Value());
} else {
opt = new OptionValueString(name, string.Value());
}
AddOptionValue(opt);
}
void ConfigVisitor::Visit(const json::Boolean& boolean) {
OptionValue *opt = new OptionValueBool(name, boolean.Value());
AddOptionValue(opt);
}
void ConfigVisitor::Visit(const json::Null& null) {
throw OptionJsonValueNull("Attempt to read null value");
}
void ConfigVisitor::AddOptionValue(OptionValue* opt) {
// Corrosponding code is in the constuctor.
std::string stripped = name.substr(1, name.rfind("/")-1);
OptionValue *opt_cur;
OptionValueMap::iterator index;
if ((index = values.find(stripped)) != values.end()) {
opt_cur = index->second;
} else {
values.insert(OptionValuePair(stripped, opt));
return;
}
int type = opt_cur->GetType();
switch (type) {
case OptionValue::Type_String:
opt_cur->SetString(opt->GetString());
break;
case OptionValue::Type_Int:
opt_cur->SetInt(opt->GetInt());
break;
case OptionValue::Type_Double:
opt_cur->SetDouble(opt->GetDouble());
break;
case OptionValue::Type_Colour:
opt_cur->SetColour(opt->GetColour());
break;
case OptionValue::Type_Bool:
opt_cur->SetBool(opt->GetBool());
break;
case OptionValue::Type_List_String: {
std::vector<std::string> array;
opt->GetListString(array);
opt_cur->SetListString(array);
break;
}
case OptionValue::Type_List_Int: {
std::vector<int64_t> array;
opt->GetListInt(array);
opt_cur->SetListInt(array);
break;
}
case OptionValue::Type_List_Double: {
std::vector<double> array;
opt->GetListDouble(array);
opt_cur->SetListDouble(array);
break;
}
case OptionValue::Type_List_Colour: {
std::vector<Colour> array;
opt->GetListColour(array);
opt_cur->SetListColour(array);
break;
}
case OptionValue::Type_List_Bool: {
std::vector<bool> array;
opt->GetListBool(array);
opt_cur->SetListBool(array);
break;
}
}
}
} // namespace agi

View file

@ -0,0 +1,83 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file option_visit.h
/// @brief Cajun JSON visitor to load config values.
/// @see option_visit.cpp
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include "libaegisub/cajun/elements.h"
#include "libaegisub/cajun/visitor.h"
#endif
#pragma once
#include "libaegisub/option.h"
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(OptionJsonValueError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueArray, OptionJsonValueError, "options/value/array")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueSingle, OptionJsonValueError, "options/value")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueNull, OptionJsonValueError, "options/value")
class ConfigVisitor : public json::ConstVisitor {
OptionValueMap &values;
std::string name;
typedef std::pair<std::string, OptionValue*> OptionValuePair;
void AddOptionValue(OptionValue* opt);
public:
ConfigVisitor(OptionValueMap &val, const std::string &member_name);
~ConfigVisitor();
void Visit(const json::Array& array);
void Visit(const json::Object& object);
void Visit(const json::Number& number);
void Visit(const json::String& string);
void Visit(const json::Boolean& boolean);
void Visit(const json::Null& null);
};
class PutOptionVisitor : public json::Visitor {
public:
bool result;
const std::string &path;
const json::UnknownElement &value;
PutOptionVisitor(const std::string &path, const json::UnknownElement &value)
: result(false), path(path), value(value)
{}
// all of these are a fail
virtual void Visit(json::Array& array) { }
virtual void Visit(json::Number& number) { }
virtual void Visit(json::String& string) { }
virtual void Visit(json::Boolean& boolean) { }
virtual void Visit(json::Null& null) { }
// this one is the win
virtual void Visit(json::Object& object) {
result = Options::PutOption(object, path, value);
}
};
} // namespace agi

View file

@ -0,0 +1,73 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file validator.cpp
/// @brief Input validation.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#endif
#include <libaegisub/validator.h>
namespace agi {
bool ValidAny::CheckType(std::string &value) {
return true;
}
bool ValidAny::Check(std::string &value) {
return true;
}
bool ValidString::CheckType(std::string &value) {
return true;
}
bool ValidString::Check(std::string &value) {
return CheckType(value);
}
bool ValidInt::CheckType(std::string &value) {
return true;
}
bool ValidInt::Check(std::string &value) {
return CheckType(value);
}
bool ValidBool::CheckType(std::string &value) {
return true;
}
bool ValidBool::Check(std::string &value) {
return CheckType(value);
}
bool ValidColour::Check(std::string &value) {
if (ValidString::CheckType(value)) {
// check if it's a valid colour
return 1;
}
return 0;
}
} // namespace agi

View file

@ -0,0 +1,58 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file access.h
/// @brief Public interface for access methods.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#endif
#include <libaegisub/exception.h>
namespace agi {
namespace acs {
DEFINE_BASE_EXCEPTION_NOINNER(AcsError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsFatal, AcsError, "acs/fatal")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsNotFound, AcsError, "acs/notfound")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsNotAFile, AcsError, "acs/file")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsNotADirectory, AcsError, "acs/directory")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsAccess, AcsError, "acs/access")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsRead, AcsAccess, "acs/access/read")
DEFINE_SIMPLE_EXCEPTION_NOINNER(AcsWrite, AcsAccess, "acs/access/write")
enum Type {
FileRead,
DirRead,
FileWrite,
DirWrite
};
void Check(const std::string &file, acs::Type);
void CheckFileRead(const std::string &file);
void CheckDirRead(const std::string &dir);
void CheckFileWrite(const std::string &file);
void CheckDirWrite(const std::string &dir);
} // namespace axs
} // namespace agi

View file

@ -0,0 +1,272 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#pragma once
#include <deque>
#include <list>
#include <string>
#include <stdexcept>
/*
TODO:
* better documentation (doxygen?)
* Unicode support
* parent element accessors
*/
namespace json
{
/////////////////////////////////////////////////
// forward declarations (more info further below)
class Visitor;
class ConstVisitor;
template <typename ValueTypeT>
class TrivialType_T;
typedef TrivialType_T<double> Number;
typedef TrivialType_T<bool> Boolean;
typedef TrivialType_T<std::string> String;
class Object;
class Array;
class Null;
/////////////////////////////////////////////////////////////////////////
// Exception - base class for all JSON-related runtime errors
class Exception : public std::runtime_error
{
public:
Exception(const std::string& sMessage);
};
/////////////////////////////////////////////////////////////////////////
// UnknownElement - provides a typesafe surrogate for any of the JSON-
// sanctioned element types. This class allows the Array and Object
// class to effectively contain a heterogeneous set of child elements.
// The cast operators provide convenient implicit downcasting, while
// preserving dynamic type safety by throwing an exception during a
// a bad cast.
// The object & array element index operators (operators [std::string]
// and [size_t]) provide convenient, quick access to child elements.
// They are a logical extension of the cast operators. These child
// element accesses can be chained together, allowing the following
// (when document structure is well-known):
// String str = objInvoices[1]["Customer"]["Company"];
class UnknownElement
{
public:
UnknownElement();
UnknownElement(const UnknownElement& unknown);
UnknownElement(const Object& object);
UnknownElement(const Array& array);
UnknownElement(const Number& number);
UnknownElement(const Boolean& boolean);
UnknownElement(const String& string);
UnknownElement(const Null& null);
~UnknownElement();
UnknownElement& operator = (const UnknownElement& unknown);
// implicit cast to actual element type. throws on failure
operator const Object& () const;
operator const Array& () const;
operator const Number& () const;
operator const Boolean& () const;
operator const String& () const;
operator const Null& () const;
// implicit cast to actual element type. *converts* on failure, and always returns success
operator Object& ();
operator Array& ();
operator Number& ();
operator Boolean& ();
operator String& ();
operator Null& ();
// provides quick access to children when real element type is object
UnknownElement& operator[] (const std::string& key);
const UnknownElement& operator[] (const std::string& key) const;
// provides quick access to children when real element type is array
UnknownElement& operator[] (size_t index);
const UnknownElement& operator[] (size_t index) const;
// implements visitor pattern
void Accept(ConstVisitor& visitor) const;
void Accept(Visitor& visitor);
// tests equality. first checks type, then value if possible
bool operator == (const UnknownElement& element) const;
private:
class Imp;
template <typename ElementTypeT>
class Imp_T;
class CastVisitor;
class ConstCastVisitor;
template <typename ElementTypeT>
class CastVisitor_T;
template <typename ElementTypeT>
class ConstCastVisitor_T;
template <typename ElementTypeT>
const ElementTypeT& CastTo() const;
template <typename ElementTypeT>
ElementTypeT& ConvertTo();
Imp* m_pImp;
};
/////////////////////////////////////////////////////////////////////////////////
// Array - mimics std::deque<UnknownElement>. The array contents are effectively
// heterogeneous thanks to the ElementUnknown class. push_back has been replaced
// by more generic insert functions.
class Array
{
public:
typedef std::deque<UnknownElement> Elements;
typedef Elements::iterator iterator;
typedef Elements::const_iterator const_iterator;
iterator Begin();
iterator End();
const_iterator Begin() const;
const_iterator End() const;
iterator Insert(const UnknownElement& element, iterator itWhere);
iterator Insert(const UnknownElement& element);
iterator Erase(iterator itWhere);
void Resize(size_t newSize);
void Clear();
size_t Size() const;
bool Empty() const;
UnknownElement& operator[] (size_t index);
const UnknownElement& operator[] (size_t index) const;
bool operator == (const Array& array) const;
private:
Elements m_Elements;
};
/////////////////////////////////////////////////////////////////////////////////
// Object - mimics std::map<std::string, UnknownElement>. The member value
// contents are effectively heterogeneous thanks to the UnknownElement class
class Object
{
public:
struct Member {
Member(const std::string& nameIn = std::string(), const UnknownElement& elementIn = UnknownElement());
bool operator == (const Member& member) const;
std::string name;
UnknownElement element;
};
typedef std::list<Member> Members; // map faster, but does not preserve order
typedef Members::iterator iterator;
typedef Members::const_iterator const_iterator;
bool operator == (const Object& object) const;
iterator Begin();
iterator End();
const_iterator Begin() const;
const_iterator End() const;
size_t Size() const;
bool Empty() const;
iterator Find(const std::string& name);
const_iterator Find(const std::string& name) const;
iterator Insert(const Member& member);
iterator Insert(const Member& member, iterator itWhere);
iterator Erase(iterator itWhere);
void Clear();
UnknownElement& operator [](const std::string& name);
const UnknownElement& operator [](const std::string& name) const;
private:
class Finder;
Members m_Members;
};
/////////////////////////////////////////////////////////////////////////////////
// TrivialType_T - class template for encapsulates a simple data type, such as
// a string, number, or boolean. Provides implicit const & noncost cast operators
// for that type, allowing "DataTypeT type = trivialType;"
template <typename DataTypeT>
class TrivialType_T
{
public:
TrivialType_T(const DataTypeT& t = DataTypeT());
operator DataTypeT&();
operator const DataTypeT&() const;
DataTypeT& Value();
const DataTypeT& Value() const;
bool operator == (const TrivialType_T<DataTypeT>& trivial) const;
private:
DataTypeT m_tValue;
};
/////////////////////////////////////////////////////////////////////////////////
// Null - doesn't do much of anything but satisfy the JSON spec. It is the default
// element type of UnknownElement
class Null
{
public:
bool operator == (const Null& trivial) const;
};
} // End namespace
#include "elements.inl"

View file

@ -0,0 +1,412 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#include "visitor.h"
#include "reader.h"
#include <cassert>
#include <algorithm>
#include <map>
/*
TODO:
* better documentation
*/
namespace json
{
inline Exception::Exception(const std::string& sMessage) :
std::runtime_error(sMessage) {}
/////////////////////////
// UnknownElement members
class UnknownElement::Imp
{
public:
virtual ~Imp() {}
virtual Imp* Clone() const = 0;
virtual bool Compare(const Imp& imp) const = 0;
virtual void Accept(ConstVisitor& visitor) const = 0;
virtual void Accept(Visitor& visitor) = 0;
};
template <typename ElementTypeT>
class UnknownElement::Imp_T : public UnknownElement::Imp
{
public:
Imp_T(const ElementTypeT& element) : m_Element(element) {}
virtual Imp* Clone() const { return new Imp_T<ElementTypeT>(*this); }
virtual void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
virtual void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
virtual bool Compare(const Imp& imp) const
{
ConstCastVisitor_T<ElementTypeT> castVisitor;
imp.Accept(castVisitor);
return castVisitor.m_pElement &&
m_Element == *castVisitor.m_pElement;
}
private:
ElementTypeT m_Element;
};
class UnknownElement::ConstCastVisitor : public ConstVisitor
{
virtual void Visit(const Array& array) {}
virtual void Visit(const Object& object) {}
virtual void Visit(const Number& number) {}
virtual void Visit(const String& string) {}
virtual void Visit(const Boolean& boolean) {}
virtual void Visit(const Null& null) {}
};
template <typename ElementTypeT>
class UnknownElement::ConstCastVisitor_T : public ConstCastVisitor
{
public:
ConstCastVisitor_T() : m_pElement(0) {}
virtual void Visit(const ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions
const ElementTypeT* m_pElement;
};
class UnknownElement::CastVisitor : public Visitor
{
virtual void Visit(Array& array) {}
virtual void Visit(Object& object) {}
virtual void Visit(Number& number) {}
virtual void Visit(String& string) {}
virtual void Visit(Boolean& boolean) {}
virtual void Visit(Null& null) {}
};
template <typename ElementTypeT>
class UnknownElement::CastVisitor_T : public CastVisitor
{
public:
CastVisitor_T() : m_pElement(0) {}
virtual void Visit(ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions
ElementTypeT* m_pElement;
};
inline UnknownElement::UnknownElement() : m_pImp( new Imp_T<Null>( Null() ) ) {}
inline UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp( unknown.m_pImp->Clone()) {}
inline UnknownElement::UnknownElement(const Object& object) : m_pImp( new Imp_T<Object>(object) ) {}
inline UnknownElement::UnknownElement(const Array& array) : m_pImp( new Imp_T<Array>(array) ) {}
inline UnknownElement::UnknownElement(const Number& number) : m_pImp( new Imp_T<Number>(number) ) {}
inline UnknownElement::UnknownElement(const Boolean& boolean) : m_pImp( new Imp_T<Boolean>(boolean) ) {}
inline UnknownElement::UnknownElement(const String& string) : m_pImp( new Imp_T<String>(string) ) {}
inline UnknownElement::UnknownElement(const Null& null) : m_pImp( new Imp_T<Null>(null) ) {}
inline UnknownElement::~UnknownElement() { delete m_pImp; }
inline UnknownElement::operator const Object& () const { return CastTo<Object>(); }
inline UnknownElement::operator const Array& () const { return CastTo<Array>(); }
inline UnknownElement::operator const Number& () const { return CastTo<Number>(); }
inline UnknownElement::operator const Boolean& () const { return CastTo<Boolean>(); }
inline UnknownElement::operator const String& () const { return CastTo<String>(); }
inline UnknownElement::operator const Null& () const { return CastTo<Null>(); }
inline UnknownElement::operator Object& () { return ConvertTo<Object>(); }
inline UnknownElement::operator Array& () { return ConvertTo<Array>(); }
inline UnknownElement::operator Number& () { return ConvertTo<Number>(); }
inline UnknownElement::operator Boolean& () { return ConvertTo<Boolean>(); }
inline UnknownElement::operator String& () { return ConvertTo<String>(); }
inline UnknownElement::operator Null& () { return ConvertTo<Null>(); }
inline UnknownElement& UnknownElement::operator = (const UnknownElement& unknown)
{
delete m_pImp;
m_pImp = unknown.m_pImp->Clone();
return *this;
}
inline UnknownElement& UnknownElement::operator[] (const std::string& key)
{
// the people want an object. make us one if we aren't already
Object& object = ConvertTo<Object>();
return object[key];
}
inline const UnknownElement& UnknownElement::operator[] (const std::string& key) const
{
// throws if we aren't an object
const Object& object = CastTo<Object>();
return object[key];
}
inline UnknownElement& UnknownElement::operator[] (size_t index)
{
// the people want an array. make us one if we aren't already
Array& array = ConvertTo<Array>();
return array[index];
}
inline const UnknownElement& UnknownElement::operator[] (size_t index) const
{
// throws if we aren't an array
const Array& array = CastTo<Array>();
return array[index];
}
template <typename ElementTypeT>
const ElementTypeT& UnknownElement::CastTo() const
{
ConstCastVisitor_T<ElementTypeT> castVisitor;
m_pImp->Accept(castVisitor);
if (castVisitor.m_pElement == 0)
throw Exception("Bad cast");
return *castVisitor.m_pElement;
}
template <typename ElementTypeT>
ElementTypeT& UnknownElement::ConvertTo()
{
CastVisitor_T<ElementTypeT> castVisitor;
m_pImp->Accept(castVisitor);
if (castVisitor.m_pElement == 0)
{
// we're not the right type. fix it & try again
*this = ElementTypeT();
m_pImp->Accept(castVisitor);
}
return *castVisitor.m_pElement;
}
inline void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); }
inline void UnknownElement::Accept(Visitor& visitor) { m_pImp->Accept(visitor); }
inline bool UnknownElement::operator == (const UnknownElement& element) const
{
return m_pImp->Compare(*element.m_pImp);
}
//////////////////
// Object members
inline Object::Member::Member(const std::string& nameIn, const UnknownElement& elementIn) :
name(nameIn), element(elementIn) {}
inline bool Object::Member::operator == (const Member& member) const
{
return name == member.name &&
element == member.element;
}
class Object::Finder : public std::unary_function<Object::Member, bool>
{
public:
Finder(const std::string& name) : m_name(name) {}
bool operator () (const Object::Member& member) {
return member.name == m_name;
}
private:
std::string m_name;
};
inline Object::iterator Object::Begin() { return m_Members.begin(); }
inline Object::iterator Object::End() { return m_Members.end(); }
inline Object::const_iterator Object::Begin() const { return m_Members.begin(); }
inline Object::const_iterator Object::End() const { return m_Members.end(); }
inline size_t Object::Size() const { return m_Members.size(); }
inline bool Object::Empty() const { return m_Members.empty(); }
inline Object::iterator Object::Find(const std::string& name)
{
return std::find_if(m_Members.begin(), m_Members.end(), Finder(name));
}
inline Object::const_iterator Object::Find(const std::string& name) const
{
return std::find_if(m_Members.begin(), m_Members.end(), Finder(name));
}
inline Object::iterator Object::Insert(const Member& member)
{
return Insert(member, End());
}
inline Object::iterator Object::Insert(const Member& member, iterator itWhere)
{
iterator it = Find(member.name);
if (it != m_Members.end())
throw Exception("Object member already exists: " + member.name);
it = m_Members.insert(itWhere, member);
return it;
}
inline Object::iterator Object::Erase(iterator itWhere)
{
return m_Members.erase(itWhere);
}
inline UnknownElement& Object::operator [](const std::string& name)
{
iterator it = Find(name);
if (it == m_Members.end())
{
Member member(name);
it = Insert(member, End());
}
return it->element;
}
inline const UnknownElement& Object::operator [](const std::string& name) const
{
const_iterator it = Find(name);
if (it == End())
throw Exception("Object member not found: " + name);
return it->element;
}
inline void Object::Clear()
{
m_Members.clear();
}
inline bool Object::operator == (const Object& object) const
{
return m_Members == object.m_Members;
}
/////////////////
// Array members
inline Array::iterator Array::Begin() { return m_Elements.begin(); }
inline Array::iterator Array::End() { return m_Elements.end(); }
inline Array::const_iterator Array::Begin() const { return m_Elements.begin(); }
inline Array::const_iterator Array::End() const { return m_Elements.end(); }
inline Array::iterator Array::Insert(const UnknownElement& element, iterator itWhere)
{
return m_Elements.insert(itWhere, element);
}
inline Array::iterator Array::Insert(const UnknownElement& element)
{
return Insert(element, End());
}
inline Array::iterator Array::Erase(iterator itWhere)
{
return m_Elements.erase(itWhere);
}
inline void Array::Resize(size_t newSize)
{
m_Elements.resize(newSize);
}
inline size_t Array::Size() const { return m_Elements.size(); }
inline bool Array::Empty() const { return m_Elements.empty(); }
inline UnknownElement& Array::operator[] (size_t index)
{
size_t nMinSize = index + 1; // zero indexed
if (m_Elements.size() < nMinSize)
m_Elements.resize(nMinSize);
return m_Elements[index];
}
inline const UnknownElement& Array::operator[] (size_t index) const
{
if (index >= m_Elements.size())
throw Exception("Array out of bounds");
return m_Elements[index];
}
inline void Array::Clear() {
m_Elements.clear();
}
inline bool Array::operator == (const Array& array) const
{
return m_Elements == array.m_Elements;
}
////////////////////////
// TrivialType_T members
template <typename DataTypeT>
TrivialType_T<DataTypeT>::TrivialType_T(const DataTypeT& t) :
m_tValue(t) {}
template <typename DataTypeT>
TrivialType_T<DataTypeT>::operator DataTypeT&()
{
return Value();
}
template <typename DataTypeT>
TrivialType_T<DataTypeT>::operator const DataTypeT&() const
{
return Value();
}
template <typename DataTypeT>
DataTypeT& TrivialType_T<DataTypeT>::Value()
{
return m_tValue;
}
template <typename DataTypeT>
const DataTypeT& TrivialType_T<DataTypeT>::Value() const
{
return m_tValue;
}
template <typename DataTypeT>
bool TrivialType_T<DataTypeT>::operator == (const TrivialType_T<DataTypeT>& trivial) const
{
return m_tValue == trivial.m_tValue;
}
//////////////////
// Null members
inline bool Null::operator == (const Null& trivial) const
{
return true;
}
} // End namespace

View file

@ -0,0 +1,125 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#pragma once
#include "elements.h"
#include <iostream>
#include <vector>
namespace json
{
class Reader
{
public:
// this structure will be reported in one of the exceptions defined below
struct Location
{
Location();
unsigned int m_nLine; // document line, zero-indexed
unsigned int m_nLineOffset; // character offset from beginning of line, zero indexed
unsigned int m_nDocOffset; // character offset from entire document, zero indexed
};
// thrown during the first phase of reading. generally catches low-level problems such
// as errant characters or corrupt/incomplete documents
class ScanException : public Exception
{
public:
ScanException(const std::string& sMessage, const Reader::Location& locError) :
Exception(sMessage),
m_locError(locError) {}
Reader::Location m_locError;
};
// thrown during the second phase of reading. generally catches higher-level problems such
// as missing commas or brackets
class ParseException : public Exception
{
public:
ParseException(const std::string& sMessage, const Reader::Location& locTokenBegin, const Reader::Location& locTokenEnd) :
Exception(sMessage),
m_locTokenBegin(locTokenBegin),
m_locTokenEnd(locTokenEnd) {}
Reader::Location m_locTokenBegin;
Reader::Location m_locTokenEnd;
};
// if you know what the document looks like, call one of these...
static void Read(Object& object, std::istream& istr);
static void Read(Array& array, std::istream& istr);
static void Read(String& string, std::istream& istr);
static void Read(Number& number, std::istream& istr);
static void Read(Boolean& boolean, std::istream& istr);
static void Read(Null& null, std::istream& istr);
// ...otherwise, if you don't know, call this & visit it
static void Read(UnknownElement& elementRoot, std::istream& istr);
private:
struct Token
{
enum Type
{
TOKEN_OBJECT_BEGIN, // {
TOKEN_OBJECT_END, // }
TOKEN_ARRAY_BEGIN, // [
TOKEN_ARRAY_END, // ]
TOKEN_NEXT_ELEMENT, // ,
TOKEN_MEMBER_ASSIGN, // :
TOKEN_STRING, // "xxx"
TOKEN_NUMBER, // [+/-]000.000[e[+/-]000]
TOKEN_BOOLEAN, // true -or- false
TOKEN_NULL // null
};
Type nType;
std::string sValue;
// for malformed file debugging
Reader::Location locBegin;
Reader::Location locEnd;
};
class InputStream;
class TokenStream;
typedef std::vector<Token> Tokens;
template <typename ElementTypeT>
static void Read_i(ElementTypeT& element, std::istream& istr);
// scanning istream into token sequence
void Scan(Tokens& tokens, InputStream& inputStream);
void EatWhiteSpace(InputStream& inputStream);
void MatchString(std::string& sValue, InputStream& inputStream);
void MatchNumber(std::string& sNumber, InputStream& inputStream);
void MatchExpectedString(const std::string& sExpected, InputStream& inputStream);
// parsing token sequence into element structure
void Parse(UnknownElement& element, TokenStream& tokenStream);
void Parse(Object& object, TokenStream& tokenStream);
void Parse(Array& array, TokenStream& tokenStream);
void Parse(String& string, TokenStream& tokenStream);
void Parse(Number& number, TokenStream& tokenStream);
void Parse(Boolean& boolean, TokenStream& tokenStream);
void Parse(Null& null, TokenStream& tokenStream);
const std::string& MatchExpectedToken(Token::Type nExpected, TokenStream& tokenStream);
};
} // End namespace
#include "reader.inl"

View file

@ -0,0 +1,519 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#include <cassert>
#include <set>
#include <sstream>
/*
TODO:
* better documentation
* unicode character decoding
*/
namespace json
{
inline std::istream& operator >> (std::istream& istr, UnknownElement& elementRoot) {
Reader::Read(elementRoot, istr);
return istr;
}
inline Reader::Location::Location() :
m_nLine(0),
m_nLineOffset(0),
m_nDocOffset(0)
{}
//////////////////////
// Reader::InputStream
class Reader::InputStream // would be cool if we could inherit from std::istream & override "get"
{
public:
InputStream(std::istream& iStr) :
m_iStr(iStr) {}
// protect access to the input stream, so we can keeep track of document/line offsets
char Get(); // big, define outside
char Peek() {
assert(m_iStr.eof() == false); // enforce reading of only valid stream data
return m_iStr.peek();
}
bool EOS() {
m_iStr.peek(); // apparently eof flag isn't set until a character read is attempted. whatever.
return m_iStr.eof();
}
const Location& GetLocation() const { return m_Location; }
private:
std::istream& m_iStr;
Location m_Location;
};
inline char Reader::InputStream::Get()
{
assert(m_iStr.eof() == false); // enforce reading of only valid stream data
char c = m_iStr.get();
++m_Location.m_nDocOffset;
if (c == '\n') {
++m_Location.m_nLine;
m_Location.m_nLineOffset = 0;
}
else {
++m_Location.m_nLineOffset;
}
return c;
}
//////////////////////
// Reader::TokenStream
class Reader::TokenStream
{
public:
TokenStream(const Tokens& tokens);
const Token& Peek();
const Token& Get();
bool EOS() const;
private:
const Tokens& m_Tokens;
Tokens::const_iterator m_itCurrent;
};
inline Reader::TokenStream::TokenStream(const Tokens& tokens) :
m_Tokens(tokens),
m_itCurrent(tokens.begin())
{}
inline const Reader::Token& Reader::TokenStream::Peek() {
assert(m_itCurrent != m_Tokens.end());
return *(m_itCurrent);
}
inline const Reader::Token& Reader::TokenStream::Get() {
assert(m_itCurrent != m_Tokens.end());
return *(m_itCurrent++);
}
inline bool Reader::TokenStream::EOS() const {
return m_itCurrent == m_Tokens.end();
}
///////////////////
// Reader (finally)
inline void Reader::Read(Object& object, std::istream& istr) { Read_i(object, istr); }
inline void Reader::Read(Array& array, std::istream& istr) { Read_i(array, istr); }
inline void Reader::Read(String& string, std::istream& istr) { Read_i(string, istr); }
inline void Reader::Read(Number& number, std::istream& istr) { Read_i(number, istr); }
inline void Reader::Read(Boolean& boolean, std::istream& istr) { Read_i(boolean, istr); }
inline void Reader::Read(Null& null, std::istream& istr) { Read_i(null, istr); }
inline void Reader::Read(UnknownElement& unknown, std::istream& istr) { Read_i(unknown, istr); }
template <typename ElementTypeT>
void Reader::Read_i(ElementTypeT& element, std::istream& istr)
{
Reader reader;
Tokens tokens;
InputStream inputStream(istr);
reader.Scan(tokens, inputStream);
TokenStream tokenStream(tokens);
reader.Parse(element, tokenStream);
if (tokenStream.EOS() == false)
{
const Token& token = tokenStream.Peek();
std::string sMessage = "Expected End of token stream; found " + token.sValue;
throw ParseException(sMessage, token.locBegin, token.locEnd);
}
}
inline void Reader::Scan(Tokens& tokens, InputStream& inputStream)
{
while (EatWhiteSpace(inputStream), // ignore any leading white space...
inputStream.EOS() == false) // ...before checking for EOS
{
// if all goes well, we'll create a token each pass
Token token;
token.locBegin = inputStream.GetLocation();
// gives us null-terminated string
std::string sChar;
sChar.push_back(inputStream.Peek());
switch (sChar[0])
{
case '{':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_OBJECT_BEGIN;
break;
case '}':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_OBJECT_END;
break;
case '[':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_ARRAY_BEGIN;
break;
case ']':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_ARRAY_END;
break;
case ',':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_NEXT_ELEMENT;
break;
case ':':
token.sValue = sChar[0];
MatchExpectedString(sChar, inputStream);
token.nType = Token::TOKEN_MEMBER_ASSIGN;
break;
case '"':
MatchString(token.sValue, inputStream);
token.nType = Token::TOKEN_STRING;
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
MatchNumber(token.sValue, inputStream);
token.nType = Token::TOKEN_NUMBER;
break;
case 't':
token.sValue = "true";
MatchExpectedString(token.sValue, inputStream);
token.nType = Token::TOKEN_BOOLEAN;
break;
case 'f':
token.sValue = "false";
MatchExpectedString(token.sValue, inputStream);
token.nType = Token::TOKEN_BOOLEAN;
break;
case 'n':
token.sValue = "null";
MatchExpectedString(token.sValue, inputStream);
token.nType = Token::TOKEN_NULL;
break;
default: {
std::string sErrorMessage = "Unexpected character in stream: " + sChar;
throw ScanException(sErrorMessage, inputStream.GetLocation());
}
}
token.locEnd = inputStream.GetLocation();
tokens.push_back(token);
}
}
inline void Reader::EatWhiteSpace(InputStream& inputStream)
{
while (inputStream.EOS() == false &&
::isspace(inputStream.Peek()))
inputStream.Get();
}
inline void Reader::MatchExpectedString(const std::string& sExpected, InputStream& inputStream)
{
std::string::const_iterator it(sExpected.begin()),
itEnd(sExpected.end());
for ( ; it != itEnd; ++it) {
if (inputStream.EOS() || // did we reach the end before finding what we're looking for...
inputStream.Get() != *it) // ...or did we find something different?
{
std::string sMessage = "Expected string: " + sExpected;
throw ScanException(sMessage, inputStream.GetLocation());
}
}
// all's well if we made it here, return quietly
}
inline void Reader::MatchString(std::string& string, InputStream& inputStream)
{
MatchExpectedString("\"", inputStream);
while (inputStream.EOS() == false &&
inputStream.Peek() != '"')
{
char c = inputStream.Get();
// escape?
if (c == '\\' &&
inputStream.EOS() == false) // shouldn't have reached the end yet
{
c = inputStream.Get();
switch (c) {
case '/': string.push_back('/'); break;
case '"': string.push_back('"'); break;
case '\\': string.push_back('\\'); break;
case 'b': string.push_back('\b'); break;
case 'f': string.push_back('\f'); break;
case 'n': string.push_back('\n'); break;
case 'r': string.push_back('\r'); break;
case 't': string.push_back('\t'); break;
case 'u': // TODO: what do we do with this?
default: {
std::string sMessage = "Unrecognized escape sequence found in string: \\" + c;
throw ScanException(sMessage, inputStream.GetLocation());
}
}
}
else {
string.push_back(c);
}
}
// eat the last '"' that we just peeked
MatchExpectedString("\"", inputStream);
}
inline void Reader::MatchNumber(std::string& sNumber, InputStream& inputStream)
{
const char sNumericChars[] = "0123456789.eE-+";
std::set<char> numericChars;
numericChars.insert(sNumericChars, sNumericChars + sizeof(sNumericChars));
while (inputStream.EOS() == false &&
numericChars.find(inputStream.Peek()) != numericChars.end())
{
sNumber.push_back(inputStream.Get());
}
}
inline void Reader::Parse(UnknownElement& element, Reader::TokenStream& tokenStream)
{
if (tokenStream.EOS()) {
std::string sMessage = "Unexpected end of token stream";
throw ParseException(sMessage, Location(), Location()); // nowhere to point to
}
const Token& token = tokenStream.Peek();
switch (token.nType) {
case Token::TOKEN_OBJECT_BEGIN:
{
// implicit non-const cast will perform conversion for us (if necessary)
Object& object = element;
Parse(object, tokenStream);
break;
}
case Token::TOKEN_ARRAY_BEGIN:
{
Array& array = element;
Parse(array, tokenStream);
break;
}
case Token::TOKEN_STRING:
{
String& string = element;
Parse(string, tokenStream);
break;
}
case Token::TOKEN_NUMBER:
{
Number& number = element;
Parse(number, tokenStream);
break;
}
case Token::TOKEN_BOOLEAN:
{
Boolean& boolean = element;
Parse(boolean, tokenStream);
break;
}
case Token::TOKEN_NULL:
{
Null& null = element;
Parse(null, tokenStream);
break;
}
default:
{
std::string sMessage = "Unexpected token: " + token.sValue;
throw ParseException(sMessage, token.locBegin, token.locEnd);
}
}
}
inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
{
MatchExpectedToken(Token::TOKEN_OBJECT_BEGIN, tokenStream);
bool bContinue = (tokenStream.EOS() == false &&
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
while (bContinue)
{
Object::Member member;
// first the member name. save the token in case we have to throw an exception
const Token& tokenName = tokenStream.Peek();
member.name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
// ...then the key/value separator...
MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream);
// ...then the value itself (can be anything).
Parse(member.element, tokenStream);
// try adding it to the object (this could throw)
try
{
object.Insert(member);
}
catch (Exception&)
{
// must be a duplicate name
std::string sMessage = "Duplicate object member token: " + member.name;
throw ParseException(sMessage, tokenName.locBegin, tokenName.locEnd);
}
bContinue = (tokenStream.EOS() == false &&
tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT);
if (bContinue)
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
}
MatchExpectedToken(Token::TOKEN_OBJECT_END, tokenStream);
}
inline void Reader::Parse(Array& array, Reader::TokenStream& tokenStream)
{
MatchExpectedToken(Token::TOKEN_ARRAY_BEGIN, tokenStream);
bool bContinue = (tokenStream.EOS() == false &&
tokenStream.Peek().nType != Token::TOKEN_ARRAY_END);
while (bContinue)
{
// ...what's next? could be anything
Array::iterator itElement = array.Insert(UnknownElement());
UnknownElement& element = *itElement;
Parse(element, tokenStream);
bContinue = (tokenStream.EOS() == false &&
tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT);
if (bContinue)
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
}
MatchExpectedToken(Token::TOKEN_ARRAY_END, tokenStream);
}
inline void Reader::Parse(String& string, Reader::TokenStream& tokenStream)
{
string = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
}
inline void Reader::Parse(Number& number, Reader::TokenStream& tokenStream)
{
const Token& currentToken = tokenStream.Peek(); // might need this later for throwing exception
const std::string& sValue = MatchExpectedToken(Token::TOKEN_NUMBER, tokenStream);
std::istringstream iStr(sValue);
double dValue;
iStr >> dValue;
// did we consume all characters in the token?
if (iStr.eof() == false)
{
std::string sMessage = "Unexpected character in NUMBER token: " + iStr.peek();
throw ParseException(sMessage, currentToken.locBegin, currentToken.locEnd);
}
number = dValue;
}
inline void Reader::Parse(Boolean& boolean, Reader::TokenStream& tokenStream)
{
const std::string& sValue = MatchExpectedToken(Token::TOKEN_BOOLEAN, tokenStream);
boolean = (sValue == "true" ? true : false);
}
inline void Reader::Parse(Null&, Reader::TokenStream& tokenStream)
{
MatchExpectedToken(Token::TOKEN_NULL, tokenStream);
}
inline const std::string& Reader::MatchExpectedToken(Token::Type nExpected, Reader::TokenStream& tokenStream)
{
if (tokenStream.EOS())
{
std::string sMessage = "Unexpected End of token stream";
throw ParseException(sMessage, Location(), Location()); // nowhere to point to
}
const Token& token = tokenStream.Get();
if (token.nType != nExpected)
{
std::string sMessage = "Unexpected token: " + token.sValue;
throw ParseException(sMessage, token.locBegin, token.locEnd);
}
return token.sValue;
}
} // End namespace

View file

@ -0,0 +1,44 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#pragma once
#include "elements.h"
namespace json
{
class Visitor
{
public:
virtual ~Visitor() {}
virtual void Visit(Array& array) = 0;
virtual void Visit(Object& object) = 0;
virtual void Visit(Number& number) = 0;
virtual void Visit(String& string) = 0;
virtual void Visit(Boolean& boolean) = 0;
virtual void Visit(Null& null) = 0;
};
class ConstVisitor
{
public:
virtual ~ConstVisitor() {}
virtual void Visit(const Array& array) = 0;
virtual void Visit(const Object& object) = 0;
virtual void Visit(const Number& number) = 0;
virtual void Visit(const String& string) = 0;
virtual void Visit(const Boolean& boolean) = 0;
virtual void Visit(const Null& null) = 0;
};
} // End namespace

View file

@ -0,0 +1,57 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#pragma once
#include "elements.h"
#include "visitor.h"
namespace json
{
class Writer : private ConstVisitor
{
public:
static void Write(const Object& object, std::ostream& ostr);
static void Write(const Array& array, std::ostream& ostr);
static void Write(const String& string, std::ostream& ostr);
static void Write(const Number& number, std::ostream& ostr);
static void Write(const Boolean& boolean, std::ostream& ostr);
static void Write(const Null& null, std::ostream& ostr);
static void Write(const UnknownElement& elementRoot, std::ostream& ostr);
private:
Writer(std::ostream& ostr);
template <typename ElementTypeT>
static void Write_i(const ElementTypeT& element, std::ostream& ostr);
void Write_i(const Object& object);
void Write_i(const Array& array);
void Write_i(const String& string);
void Write_i(const Number& number);
void Write_i(const Boolean& boolean);
void Write_i(const Null& null);
void Write_i(const UnknownElement& unknown);
virtual void Visit(const Array& array);
virtual void Visit(const Object& object);
virtual void Visit(const Number& number);
virtual void Visit(const String& string);
virtual void Visit(const Boolean& boolean);
virtual void Visit(const Null& null);
std::ostream& m_ostr;
int m_nTabDepth;
};
} // End namespace
#include "writer.inl"

View file

@ -0,0 +1,153 @@
/**********************************************
License: BSD
Project Webpage: http://cajun-jsonapi.sourceforge.net/
Author: Terry Caton
***********************************************/
#include "writer.h"
#include <iostream>
#include <iomanip>
/*
TODO:
* better documentation
* unicode character encoding
*/
namespace json
{
inline void Writer::Write(const UnknownElement& elementRoot, std::ostream& ostr) { Write_i(elementRoot, ostr); }
inline void Writer::Write(const Object& object, std::ostream& ostr) { Write_i(object, ostr); }
inline void Writer::Write(const Array& array, std::ostream& ostr) { Write_i(array, ostr); }
inline void Writer::Write(const Number& number, std::ostream& ostr) { Write_i(number, ostr); }
inline void Writer::Write(const String& string, std::ostream& ostr) { Write_i(string, ostr); }
inline void Writer::Write(const Boolean& boolean, std::ostream& ostr) { Write_i(boolean, ostr); }
inline void Writer::Write(const Null& null, std::ostream& ostr) { Write_i(null, ostr); }
inline Writer::Writer(std::ostream& ostr) :
m_ostr(ostr),
m_nTabDepth(0)
{}
template <typename ElementTypeT>
void Writer::Write_i(const ElementTypeT& element, std::ostream& ostr)
{
Writer writer(ostr);
writer.Write_i(element);
ostr.flush(); // all done
}
inline void Writer::Write_i(const Array& array)
{
if (array.Empty())
m_ostr << "[]";
else
{
m_ostr << '[' << std::endl;
++m_nTabDepth;
Array::const_iterator it(array.Begin()),
itEnd(array.End());
while (it != itEnd) {
m_ostr << std::string(m_nTabDepth, '\t');
Write_i(*it);
if (++it != itEnd)
m_ostr << ',';
m_ostr << std::endl;
}
--m_nTabDepth;
m_ostr << std::string(m_nTabDepth, '\t') << ']';
}
}
inline void Writer::Write_i(const Object& object)
{
if (object.Empty())
m_ostr << "{}";
else
{
m_ostr << '{' << std::endl;
++m_nTabDepth;
Object::const_iterator it(object.Begin()),
itEnd(object.End());
while (it != itEnd) {
m_ostr << std::string(m_nTabDepth, '\t') << '"' << it->name << "\" : ";
Write_i(it->element);
if (++it != itEnd)
m_ostr << ',';
m_ostr << std::endl;
}
--m_nTabDepth;
m_ostr << std::string(m_nTabDepth, '\t') << '}';
}
}
inline void Writer::Write_i(const Number& numberElement)
{
m_ostr << std::setprecision(20) << numberElement.Value();
}
inline void Writer::Write_i(const Boolean& booleanElement)
{
m_ostr << (booleanElement.Value() ? "true" : "false");
}
inline void Writer::Write_i(const String& stringElement)
{
m_ostr << '"';
const std::string& s = stringElement.Value();
std::string::const_iterator it(s.begin()),
itEnd(s.end());
for (; it != itEnd; ++it)
{
switch (*it)
{
case '"': m_ostr << "\\\""; break;
case '\\': m_ostr << "\\\\"; break;
case '\b': m_ostr << "\\b"; break;
case '\f': m_ostr << "\\f"; break;
case '\n': m_ostr << "\\n"; break;
case '\r': m_ostr << "\\r"; break;
case '\t': m_ostr << "\\t"; break;
//case '\u': m_ostr << ""; break; ??
default: m_ostr << *it; break;
}
}
m_ostr << '"';
}
inline void Writer::Write_i(const Null& )
{
m_ostr << "null";
}
inline void Writer::Write_i(const UnknownElement& unknown)
{
unknown.Accept(*this);
}
inline void Writer::Visit(const Array& array) { Write_i(array); }
inline void Writer::Visit(const Object& object) { Write_i(object); }
inline void Writer::Visit(const Number& number) { Write_i(number); }
inline void Writer::Visit(const String& string) { Write_i(string); }
inline void Writer::Visit(const Boolean& boolean) { Write_i(boolean); }
inline void Writer::Visit(const Null& null) { Write_i(null); }
} // End namespace

View file

@ -0,0 +1,31 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file colour.h
/// @brief Colourspace class and functions.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <string>
#endif
// This file is a stub for now.
namespace agi {
typedef std::string Colour;
} // namespace agi

View file

@ -36,13 +36,10 @@
#pragma once
#ifndef AGI_PRE
#include <wx/string.h>
#endif
#include <string>
/// @see aegisub.h
namespace Aegisub {
namespace agi {
/// @class Exception
@ -61,11 +58,11 @@ namespace Aegisub {
/// When throwing exceptions, throw temporaries, not heap allocated
/// objects. (C++ FAQ Lite 17.6.) I.e. this is correct:
/// @code
/// throw Aegisub::SomeException(_T("Message for exception"));
/// throw Aegisub::SomeException("Message for exception");
/// @endcode
/// This is wrong:
/// @code
/// throw new Aegisub::SomeException(_T("Remember this is the wrong way!"));
/// throw new Aegisub::SomeException("Remember this is the wrong way!");
/// @endcode
/// Exceptions must not be allocated on heap, because of the risks of
/// leaking memory that way. (C++ FAQ Lite 17.8.)
@ -96,7 +93,7 @@ namespace Aegisub {
class Exception {
/// The error message
wxString message;
std::string message;
/// An inner exception, the cause of this exception
Exception *inner;
@ -109,7 +106,7 @@ namespace Aegisub {
///
/// Deriving classes should always use this constructor for initialising
/// the base class.
Exception(const wxString &msg, const Exception *inr = 0)
Exception(const std::string &msg, const Exception *inr = 0)
: message(msg)
, inner(0)
{
@ -136,7 +133,7 @@ namespace Aegisub {
/// @brief Get the outer exception error message
/// @return Error message
virtual wxString GetMessage() const { return message; }
virtual std::string GetMessage() const { return message; }
/// @brief Get error messages for chained exceptions
/// @return Chained error message
@ -144,7 +141,7 @@ namespace Aegisub {
/// If there is an inner exception, prepend its chained error message to
/// our error message, with a CRLF between. Returns our own error message
/// alone if there is no inner exception.
wxString GetChainedMessage() const { if (inner) return inner->GetChainedMessage() + _T("\r\n") + GetMessage(); else return GetMessage(); }
std::string GetChainedMessage() const { if (inner) return inner->GetChainedMessage() + "\r\n" + GetMessage(); else return GetMessage(); }
/// @brief Exception class printable name
///
@ -155,16 +152,16 @@ namespace Aegisub {
/// name for their sub-tree, further sub-classes add further levels, each
/// level is separated by a slash. Characters allowed in the name for a
/// level are [a-z0-9_].
virtual const wxChar * GetName() const = 0;
virtual const char * GetName() const = 0;
/// @brief Convert to wxChar array as the error message
/// @brief Convert to char array as the error message
/// @return The error message
operator const wxChar * () { return GetMessage().c_str(); }
operator const char * () { return GetMessage().c_str(); }
/// @brief Convert to wxString as the error message
/// @brief Convert to std::string as the error message
/// @return The error message
operator wxString () { return GetMessage(); }
operator std::string () { return GetMessage(); }
/// @brief Create a copy of the exception allocated on the heap
/// @return A heap-allocated exception object
@ -180,7 +177,7 @@ namespace Aegisub {
///
/// Intended for use in error messages where it can sometimes be convenient to
/// indicate the exact position the error occurred at.
#define AG_WHERE _T(" (at ") _T(__FILE__) _T(":") _T(#__LINE__) _T(")")
#define AG_WHERE " (at " __FILE__ ":" #__LINE__ ")"
@ -194,8 +191,8 @@ namespace Aegisub {
#define DEFINE_SIMPLE_EXCEPTION_NOINNER(classname,baseclass,displayname) \
class classname : public baseclass { \
public: \
classname(const wxString &msg) : baseclass(msg) { } \
const wxChar * GetName() const { return _T(displayname); } \
classname(const std::string &msg) : baseclass(msg) { } \
const char * GetName() const { return displayname; } \
Exception * Copy() const { return new classname(*this); } \
};
@ -209,8 +206,8 @@ namespace Aegisub {
#define DEFINE_SIMPLE_EXCEPTION(classname,baseclass,displayname) \
class classname : public baseclass { \
public: \
classname(const wxString &msg, Exception *inner) : baseclass(msg, inner) { } \
const wxChar * GetName() const { return _T(displayname); } \
classname(const std::string &msg, Exception *inner) : baseclass(msg, inner) { } \
const char * GetName() const { return displayname; } \
Exception * Copy() const { return new classname(*this); } \
};
@ -224,7 +221,7 @@ namespace Aegisub {
#define DEFINE_BASE_EXCEPTION_NOINNER(classname,baseclass) \
class classname : public baseclass { \
public: \
classname(const wxString &msg) : baseclass(msg) { } \
classname(const std::string &msg) : baseclass(msg) { } \
};
/// @brief Macro for declaring non-instantiable exception base classes with inner
@ -238,7 +235,7 @@ namespace Aegisub {
#define DEFINE_BASE_EXCEPTION(classname,baseclass) \
class classname : public baseclass { \
public: \
classname(const wxString &msg, Exception *inner) : baseclass(msg, inner) { } \
classname(const std::string &msg, Exception *inner) : baseclass(msg, inner) { } \
};
@ -291,10 +288,10 @@ namespace Aegisub {
/// @brief Constructor, automatically builds the error message
/// @param filename Name of the file that could not be found
FileNotFoundError(const wxString &filename) : FileNotAccessibleError(wxString(_T("File not found: ")) + filename) { }
FileNotFoundError(const std::string &filename) : FileNotAccessibleError(std::string("File not found: ") + filename) { }
// Not documented, see Aegisub::Exception class
const wxChar * GetName() const { return _T("filesystem/not_accessible/not_found"); }
const char * GetName() const { return "filesystem/not_accessible/not_found"; }
// Not documented, see Aegisub::Exception class
Exception * Copy() const { return new FileNotFoundError(*this); } \

View file

@ -0,0 +1,57 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file io.h
/// @brief Public interface for IO methods.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#endif
#include <libaegisub/exception.h>
namespace agi {
namespace io {
DEFINE_BASE_EXCEPTION_NOINNER(IOError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(IOFatal, IOError, "io/fatal")
/*
DEFINE_SIMPLE_EXCEPTION_NOINNER(IOAccess, IOError, "io/access")
DEFINE_SIMPLE_EXCEPTION_NOINNER(IONotFound, IOError, "io/notfound")
DEFINE_SIMPLE_EXCEPTION_NOINNER(IONotAFile, IOError, "io/file")
DEFINE_SIMPLE_EXCEPTION_NOINNER(IONotADirectory, IOError, "io/directory")
DEFINE_SIMPLE_EXCEPTION_NOINNER(IOAccessRead, IOError, "io/read")
DEFINE_SIMPLE_EXCEPTION_NOINNER(IOAccessWrite, IOError, "io/write")
*/
std::ifstream* Open(const std::string &file);
class Save {
std::ofstream *fp;
const std::string file_name;
public:
Save(const std::string& file);
~Save();
std::ofstream& Get();
};
} // namespace io
} // namespace agi

View file

@ -0,0 +1,104 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file mru.h
/// @brief Public interface for MRU (Most Recently Used) lists.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <map>
#include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/writer.h"
#include "libaegisub/cajun/elements.h"
#endif
#include <libaegisub/exception.h>
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(MRUError,Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(MRUErrorInvalidKey, MRUError, "mru/invalid")
DEFINE_SIMPLE_EXCEPTION_NOINNER(MRUErrorIndexOutOfRange, MRUError, "mru/invalid")
/// @class MRUManager
/// @brief Most Recently Used (MRU) list handling
///
/// Add() should be called anytime a file is opened, this will either add the
/// entry or update it if it already exists.
///
/// If a file fails to open, Remove() should be called.
///
class MRUManager {
public:
/// @brief Map for time->value pairs.
/// @param int Last time loaded
/// @param std::string File or value that was last loaded.
typedef std::multimap<time_t, std::string, std::greater_equal<time_t> > MRUListMap;
/// @brief Constructor
/// @param config File to load MRU values from
MRUManager(const std::string &config, const std::string &default_config);
/// Destructor
~MRUManager();
/// @brief Add entry to the list.
/// @param key List name
/// @param entry Entry to add
/// @exception MRUErrorInvalidKey thrown when an invalid key is used.
void Add(const std::string &key, const std::string &entry);
/// @brief Remove entry from the list.
/// @param key List name
/// @param entry Entry to add
/// @exception MRUErrorInvalidKey thrown when an invalid key is used.
void Remove(const std::string &key, const std::string &entry);
/// @brief Return list
/// @param key List name
/// @exception MRUErrorInvalidKey thrown when an invalid key is used.
const MRUListMap* Get(const std::string &key);
/// @brief Return A single entry in a list.
/// @param key List name
/// @param entry 0-base position of entry
/// @exception MRUErrorInvalidKey thrown when an invalid key is used.
const std::string GetEntry(const std::string &key, const int entry);
/// Write MRU lists to disk.
void Flush();
private:
/// Internal name of the config file, set during object construction.
const std::string config_name;
/// @brief Map for MRUListMap values.
/// @param std::string Name
/// @param MRUListMap instance.
typedef std::map<std::string, MRUListMap*> MRUMap;
/// Internal MRUMap values.
MRUMap mru;
void Load(const std::string &key, const json::Array& array);
inline void Prune(MRUListMap& map);
};
} // namespace agi

View file

@ -0,0 +1,120 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file option.h
/// @brief Public interface for option values.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/writer.h"
#include "libaegisub/cajun/elements.h"
#endif
#include <libaegisub/exception.h>
#include <libaegisub/option_value.h>
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(OptionError,Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionErrorNotFound, OptionError, "options/not_found")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionErrorDuplicateKey, OptionError, "options/dump/duplicate")
/// This is a cool trick: make a class un-copyable, in this case we always want
/// to update our *original* map, this will ensure that it is always updated in
/// every situation.
class OptionValueMap : public std::map<std::string,OptionValue*> {
private:
OptionValueMap(const OptionValueMap& x);
OptionValueMap& operator=(const OptionValueMap& x);
public:
OptionValueMap() {};
};
class Options {
friend class PutOptionVisitor;
/// Root json::Object, used for loading.
json::UnknownElement config_root;
/// Internal OptionValueMap
OptionValueMap values;
/// @brief Create option object.
/// @param path Path to store
json::Object CreateObject(std::string path);
/// User config (file that will be written to disk)
const std::string config_file;
/// Default config (for use when config file is/gets corrupted)
const std::string config_default;
/// Whether the user (final) config has been loaded
bool config_loaded;
/// @brief Load a config file into the Options object.
/// @param config Config to load.
void LoadConfig(std::istream& stream);
protected:
/// @brief Write an option to file.
/// @param[out] obj Parent object
/// @param[in] path Path option should be stored in.
/// @param[in] value Value to write.
static bool PutOption(json::Object &obj, const std::string &path, const json::UnknownElement &value);
public:
/// @brief Constructor
/// @param file User config that will be loaded from and written back to.
/// @param default_config Default configuration.
Options(const std::string &file, const std::string &default_config);
/// Destructor
~Options();
/// @brief Get an option by name.
/// @param name Option to get.
/// Get an option value object by name throw an internal exception if the option is not found.
OptionValue* Get(const std::string &name);
/// @brief Next configuration file to load.
/// @param[in] src Stream to load from.
/// Load next config which will superceed any values from previous configs
/// can be called as many times as required, but only after ConfigDefault() and
/// before ConfigUser()
void ConfigNext(std::istream &stream);
/// @brief Set user config file.
/// Set the user configuration file and read options from it, closes all possible
/// config file loading and sets the file to write to.
void ConfigUser();
/// Write the user configuration to disk, throws an exeption if something goes wrong.
void Flush();
/// Print internal option type, name and values.
void DumpAll();
};
} // namespace agi

View file

@ -0,0 +1,199 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file option_value.h
/// @brief Container for holding an actual option value.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <stdint.h>
#include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/writer.h"
#include "libaegisub/cajun/elements.h"
#endif
#include <libaegisub/exception.h>
#include <libaegisub/colour.h>
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(OptionValueError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorNotFound, OptionValueError, "options/not_found")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidListType, OptionValueError, "options/array/invalid_type")
class OptionValue;
class ConfigVisitor;
/// @class OptionValueListener
/// Inherit from this class to get the proper type for the notification callback
/// signature.
class OptionValueListener {
public:
// (I might have messed up the syntax here. It's supposed to be a pointer
// to a member function of an OptionValueListener-derived class.)
typedef void (OptionValueListener::*ChangeEvent)(const OptionValue *option);
};
/// @class OptionValue
/// Holds an actual option.
class OptionValue {
std::set<OptionValueListener*> listeners;
protected:
void NotifyChanged();
public:
OptionValue() {};
virtual ~OptionValue() {};
/// Option type
/// No bitsets here.
enum OptionType {
Type_String = 0, ///< String
Type_Int = 1, ///< Integer
Type_Double = 2, ///< Double
Type_Colour = 3, ///< Colour
Type_Bool = 4, ///< Bool
Type_List_String = 100, ///< List of Strings
Type_List_Int = 101, ///< List of Integers
Type_List_Double = 102, ///< List of Doubles
Type_List_Colour = 103, ///< List of Colours
Type_List_Bool = 104 ///< List of Bools
};
virtual OptionType GetType() const = 0;
virtual std::string GetName() const = 0;
virtual bool IsDefault() const = 0;
virtual void Reset() = 0;
virtual std::string GetString() const { throw OptionValueErrorInvalidType("Attempt to retrieve string from non-string value"); }
virtual int64_t GetInt() const { throw OptionValueErrorInvalidType("Attempt to retrieve int from non-int value"); }
virtual double GetDouble() const { throw OptionValueErrorInvalidType("Attempt to retrieve double from non-double value"); }
virtual Colour GetColour() const { throw OptionValueErrorInvalidType("Attempt to retrieve colour from non-colour value"); }
virtual bool GetBool() const { throw OptionValueErrorInvalidType("Attempt to retrieve bool from non-bool value"); }
virtual void SetString(const std::string val) { throw OptionValueErrorInvalidType("Attempt to set string in a non-string value"); }
virtual void SetInt(const int64_t val) { throw OptionValueErrorInvalidType("Attempt to set int in a non-int value"); }
virtual void SetDouble(const double val) { throw OptionValueErrorInvalidType("Attempt to set double in a non-double value"); }
virtual void SetColour(const Colour val) { throw OptionValueErrorInvalidType("Attempt to set colour in a non-colour value"); }
virtual void SetBool(const bool val) { throw OptionValueErrorInvalidType("Attempt to set bool in a non-bool value"); }
virtual std::string GetDefaultString() const { throw OptionValueErrorInvalidType("Attempt to retrieve string from non-string value"); }
virtual int64_t GetDefaultInt() const { throw OptionValueErrorInvalidType("Attempt to retrieve int from non-int value"); }
virtual double GetDefaultDouble() const { throw OptionValueErrorInvalidType("Attempt to retrieve double from non-double value"); }
virtual Colour GetDefaultColour() const { throw OptionValueErrorInvalidType("Attempt to retrieve colour from non-colour value"); }
virtual bool GetDefaultBool() const { throw OptionValueErrorInvalidType("Attempt to retrieve bool from non-bool value"); }
virtual void GetListString(std::vector<std::string> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string list from non-string list"); }
virtual void GetListInt(std::vector<int64_t> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive int list from non-int list"); }
virtual void GetListDouble(std::vector<double> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive double list from non-double list"); }
virtual void GetListColour(std::vector<Colour> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive colour list from non-colour list"); }
virtual void GetListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); }
virtual void SetListString(const std::vector<std::string> val) { throw OptionValueErrorInvalidListType("Attempt to set string list in a non-string list"); }
virtual void SetListInt(const std::vector<int64_t> val) { throw OptionValueErrorInvalidListType("Attempt to set int list in a non-int list"); }
virtual void SetListDouble(const std::vector<double> val) { throw OptionValueErrorInvalidListType("Attempt to set double list in a non-double list"); }
virtual void SetListColour(const std::vector<Colour> val) { throw OptionValueErrorInvalidListType("Attempt to set colour list in a non-colour list"); }
virtual void SetListBool(const std::vector<bool> val) { throw OptionValueErrorInvalidListType("Attempt to set string in a non-bool list"); }
virtual void GetDefaultListString(std::vector<std::string> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string list from non-string list"); }
virtual void GetDefaultListInt(std::vector<int64_t> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive int list from non-int list"); }
virtual void GetDefaultListDouble(std::vector<double> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive double list from non-double list"); }
virtual void GetDefaultListColour(std::vector<Colour> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive colour list from non-colour list"); }
virtual void GetDefaultListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); }
void Subscribe(OptionValueListener*);
void Unsubscribe(OptionValueListener*);
void Subscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
void Unsubscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
};
#define CONFIG_OPTIONVALUE(type_name, type) \
class OptionValue##type_name : public OptionValue { \
type value; \
type value_default; \
std::string name; \
public: \
OptionValue##type_name(std::string member_name, type member_value): \
value(member_value), name(member_name) {} \
type Get##type_name() const { return value; } \
void Set##type_name(const type new_val) { value = new_val; } \
type GetDefault##type_name() const { return value_default; } \
OptionType GetType() const { return OptionValue::Type_##type_name; } \
std::string GetName() const { return name; } \
void Reset() { value = value_default; } \
bool IsDefault() const { return (value == value_default) ? 1 : 0; } \
};
CONFIG_OPTIONVALUE(String, std::string)
CONFIG_OPTIONVALUE(Int, int64_t)
CONFIG_OPTIONVALUE(Double, double)
CONFIG_OPTIONVALUE(Colour, Colour)
CONFIG_OPTIONVALUE(Bool, bool)
class OptionValueList: public OptionValue {
friend class ConfigVisitor;
protected:
OptionValueList() {};
virtual ~OptionValueList() {};
virtual void InsertString(const std::string val) { throw OptionValueErrorInvalidListType("Attempt to insert string in a non-string list"); }
virtual void InsertInt(const int64_t val) { throw OptionValueErrorInvalidListType("Attempt to insert int in a non-int list"); }
virtual void InsertDouble(const double val) { throw OptionValueErrorInvalidListType("Attempt to insert double in a non-double list"); }
virtual void InsertColour(const Colour val) { throw OptionValueErrorInvalidListType("Attempt insert set colour in a from non-colour list"); }
virtual void InsertBool(const bool val) { throw OptionValueErrorInvalidListType("Attempt to insert bool in a non-bool list"); }
};
#define CONFIG_OPTIONVALUE_LIST(type_name, type) \
class OptionValueList##type_name : public OptionValueList { \
std::vector<type> array; \
std::vector<type> array_default; \
std::string name; \
void Insert##type_name(const type val) { array.push_back(val); } \
public: \
virtual std::string GetString() const { return "";} \
OptionValueList##type_name(std::string member_name): name(member_name) {} \
void GetList##type_name(std::vector<type> &out) const { out = array; } \
void SetList##type_name(const std::vector<type> val) { array = val;} \
void GetDefaultList##type_name(std::vector<type> &out) const { out = array_default; } \
OptionType GetType() const { return OptionValue::Type_List_##type_name; } \
std::string GetName() const { return name; } \
void Reset() { array = array_default; } \
bool IsDefault() const { return (array == array_default) ? 1 : 0; } \
};
CONFIG_OPTIONVALUE_LIST(String, std::string)
CONFIG_OPTIONVALUE_LIST(Int, int64_t)
CONFIG_OPTIONVALUE_LIST(Double, double)
CONFIG_OPTIONVALUE_LIST(Colour, Colour)
CONFIG_OPTIONVALUE_LIST(Bool, bool)
} // namespace agi

View file

@ -0,0 +1,36 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file util.h
/// @brief Public interface for general utilities.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <string>
#include <stdio.h>
#endif
#include <libaegisub/access.h>
namespace agi {
namespace util {
const std::string DirName(const std::string& path);
void Rename(const std::string& from, const std::string& to);
} // namespace util
} // namespace agi

View file

@ -0,0 +1,83 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file validator.h
/// @brief Input validation.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#endif
#include <libaegisub/colour.h>
namespace agi {
class Validator {
public:
/// Types supported.
enum ValidType {
Type_Any = 0, ///< Any (should be used instead of "String"
/// to accept any value for code clarity.)
Type_String = 1, ///< String
Type_Int = 2, ///< Integer
Type_Bool = 3, ///< Bool
Type_Colour = 4 ///< Colour
};
/// @brief Check value type.
/// @param value Value
/// @return true/false
///
/// If the value type is "int" or "string" it will return true/false based on this alone.
/// This should validate against full values or single characters to make it suitable for input boxes.
virtual bool CheckType(std::string &value)=0;
/// @brief Check value including constraints.
/// @param value Value
/// @return true/false
///
/// Check value including bounds checking.
/// CheckType() should always be the first function called.
virtual bool Check(std::string &value)=0;
/// @brief Return validation type.
/// @return Type
virtual ValidType GetType()=0;
};
#define VALID_BASE(type_name) \
class Valid##type_name : public Validator { \
public: \
ValidType GetType() { return Type_##type_name; } \
bool CheckType(std::string &value); \
virtual bool Check(std::string &value); \
};
VALID_BASE(Any)
VALID_BASE(String)
VALID_BASE(Int)
VALID_BASE(Bool)
class ValidColour: public ValidString {
public:
ValidType GetType() { return Type_Colour; }
virtual bool Check(std::string &value);
};
} // namespace agi

View file

@ -0,0 +1,23 @@
#define LAGI_PRE
#include <errno.h>
#include <io.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/stat.h>
#include <time.h>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include "libaegisub/cajun/elements.h"
#include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/visitor.h"
#include "libaegisub/cajun/writer.h"
#define LAGI_PRE

View file

@ -0,0 +1,109 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file access.cpp
/// @brief Unix access methods.
/// @ingroup libaegisub unix
#ifndef LAGI_PRE
#include <sys/stat.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#endif
#include "libaegisub/util.h"
namespace agi {
namespace acs {
void CheckFileRead(const std::string &file) {
Check(file, acs::FileRead);
}
void CheckFileWrite(const std::string &file) {
Check(file, acs::FileWrite);
}
void CheckDirRead(const std::string &dir) {
Check(dir, acs::DirRead);
}
void CheckDirWrite(const std::string &dir) {
Check(dir, acs::DirWrite);
}
void Check(const std::string &file, acs::Type type) {
struct stat file_stat;
int file_status;
file_status = stat(file.c_str(), &file_stat);
if (file_status != 0) {
switch (errno) {
case ENOENT:
throw AcsNotFound("File or path not found.");
break;
case EACCES:
throw AcsAccess("Access Denied to file, path or path component.");
break;
case EIO:
throw AcsFatal("Fatal I/O error occurred.");
break;
}
}
switch (type) {
case FileRead:
case FileWrite:
if ((file_stat.st_mode & S_IFREG) == 0)
throw AcsNotAFile("Not a file.");
break;
case DirRead:
case DirWrite:
if ((file_stat.st_mode & S_IFDIR) == 0)
throw AcsNotADirectory("Not a directory.");
break;
}
switch (type) {
case DirRead:
case FileRead:
file_status = access(file.c_str(), R_OK);
if (file_status != 0)
throw AcsRead("File or directory is not readable.");
break;
case DirWrite:
case FileWrite:
file_status = access(file.c_str(), W_OK);
if (file_status != 0)
throw AcsWrite("File or directory is not writable.");
break;
}
}
} // namespace acs
} // namespace agi

View file

@ -0,0 +1,87 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file io.cpp
/// @brief Unix IO methods.
/// @ingroup libaegisub unix
#ifndef LAGI_PRE
#include <sys/stat.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#endif
#include "libaegisub/io.h"
#include "libaegisub/util.h"
namespace agi {
namespace io {
std::ifstream* Open(const std::string &file) {
acs::CheckFileRead(file);
std::ifstream *stream = new std::ifstream(file.c_str());
if (stream->fail())
throw IOFatal("Unknown fatal error as occurred");
return stream;
}
Save::Save(const std::string& file): file_name(file) {
const std::string pwd = util::DirName(file);
acs::CheckDirWrite(pwd.c_str());
try {
acs::CheckFileWrite(file);
} catch (acs::AcsNotFound& e) {
// If the file doesn't exist we create a 0 byte file, this so so
// util::Rename will find it, and to let users know something went
// wrong by leaving a 0 byte file.
std::ofstream fp_touch(file.c_str());
fp_touch.close();
}
/// @todo This is a temp hack, proper implementation needs to come after
/// Windows support is added. The code in the destructor needs fixing
/// as well.
const std::string tmp = file + "_tmp";
// This will open to file.XXXX. (tempfile)
fp = new std::ofstream(tmp.c_str());
}
Save::~Save() {
const std::string tmp(file_name + "_tmp");
util::Rename(tmp, file_name);
delete fp;
fp = 0; // to avoid any silly errors.
}
std::ofstream& Save::Get() {
return *fp;
}
} // namespace io
} // namespace agi

View file

@ -0,0 +1,59 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file util.cpp
/// @brief Unix utility methods.
/// @ingroup libaegisub unix
#ifndef LAGI_PRE
#include <stdarg.h>
#include <stdio.h>
#include <string>
#include <fstream>
#endif
#include <string.h>
#include "libaegisub/util.h"
namespace agi {
namespace util {
const std::string DirName(const std::string& path) {
if (path.find('/') == std::string::npos) {
const std::string cwd(".");
return cwd;
}
const std::string stripped = path.substr(0, path.rfind("/")+1);
return stripped;
}
void Rename(const std::string& from, const std::string& to) {
acs::CheckFileWrite(from);
try {
acs::CheckFileWrite(to);
} catch (acs::AcsNotFound& e) {
acs::CheckDirWrite(DirName(to));
}
rename(from.c_str(), to.c_str());
}
} // namespace io
} // namespace agi

View file

@ -0,0 +1,118 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file access.cpp
/// @brief Windows access methods.
/// @ingroup libaegisub windows
#ifndef LAGI_PRE
#include <sys/stat.h>
#include <io.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#endif
#ifndef R_OK
#define R_OK 04
#endif
#ifndef W_OK
#define W_OK 02
#endif
#pragma warning(disable: 4996)
#include "libaegisub/util.h"
namespace agi {
namespace acs {
void CheckFileRead(const std::string &file) {
Check(file, acs::FileRead);
}
void CheckFileWrite(const std::string &file) {
Check(file, acs::FileWrite);
}
void CheckDirRead(const std::string &dir) {
Check(dir, acs::DirRead);
}
void CheckDirWrite(const std::string &dir) {
Check(dir, acs::DirWrite);
}
void Check(const std::string &file, acs::Type type) {
struct stat file_stat;
int file_status;
file_status = stat(file.c_str(), &file_stat);
if (file_status != 0) {
switch (errno) {
case ENOENT:
throw AcsNotFound("File or path not found.");
break;
case EACCES:
throw AcsAccess("Access Denied to file, path or path component.");
break;
case EIO:
throw AcsFatal("Fatal I/O error occurred.");
break;
}
}
switch (type) {
case FileRead:
case FileWrite:
if ((file_stat.st_mode & S_IFREG) == 0)
throw AcsNotAFile("Not a file.");
break;
case DirRead:
case DirWrite:
if ((file_stat.st_mode & S_IFDIR) == 0)
throw AcsNotADirectory("Not a directory.");
break;
}
switch (type) {
case DirRead:
case FileRead:
file_status = access(file.c_str(), R_OK);
if (file_status != 0)
throw AcsRead("File or directory is not readable.");
break;
case DirWrite:
case FileWrite:
file_status = access(file.c_str(), W_OK);
if (file_status != 0)
throw AcsWrite("File or directory is not writable.");
break;
}
}
}
}

View file

@ -0,0 +1,89 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file io.cpp
/// @brief Windows IO methods.
/// @ingroup libaegisub windows
#ifndef LAGI_PRE
#include <sys/stat.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#endif
#include "libaegisub/io.h"
#include "libaegisub/util.h"
namespace agi {
namespace io {
std::ifstream* Open(const std::string &file) {
acs::CheckFileRead(file);
std::ifstream *stream = new std::ifstream(file.c_str());
if (stream->fail()) {
delete stream;
throw IOFatal("Unknown fatal error as occurred");
}
return stream;
}
Save::Save(const std::string& file): file_name(file) {
const std::string pwd = util::DirName(file);
acs::CheckDirWrite(pwd.c_str());
try {
acs::CheckFileWrite(file);
} catch (acs::AcsNotFound&) {
// If the file doesn't exist we create a 0 byte file, this so so
// util::Rename will find it, and to let users know something went
// wrong by leaving a 0 byte file.
std::ofstream fp_touch(file.c_str());
fp_touch.close();
}
/// @todo This is a temp hack, proper implementation needs to come after
/// Windows support is added. The code in the destructor needs fixing
/// as well.
const std::string tmp = file + "_tmp";
// This will open to file.XXXX. (tempfile)
fp = new std::ofstream(tmp.c_str());
}
Save::~Save() {
const std::string tmp(file_name + "_tmp");
util::Rename(tmp, file_name);
delete fp;
fp = 0; // to avoid any silly errors.
}
std::ofstream& Save::Get() {
return *fp;
}
} // namespace io
} // namespace agi

View file

View file

@ -0,0 +1,59 @@
// Copyright (c) 2010, Amar Takhar <verm@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.
//
// $Id$
/// @file util.cpp
/// @brief Windows utility methods.
/// @ingroup libaegisub windows
#ifndef LAGI_PRE
#include <stdarg.h>
#include <stdio.h>
#include <string>
#include <fstream>
#endif
#include <string.h>
#include "libaegisub/util.h"
namespace agi {
namespace util {
const std::string DirName(const std::string& path) {
if (path.find('/') == std::string::npos) {
const std::string cwd(".");
return cwd;
}
const std::string stripped = path.substr(0, path.rfind("/")+1);
return stripped;
}
void Rename(const std::string& from, const std::string& to) {
acs::CheckFileWrite(from);
try {
acs::CheckFileWrite(to);
} catch (acs::AcsNotFound&) {
acs::CheckDirWrite(DirName(to));
}
rename(from.c_str(), to.c_str());
}
} // namespace io
} // namespace agi

View file

@ -23,10 +23,10 @@ SUBDIRS = \
libresrc \
$(libosxutil_subdir)
AM_CXXFLAGS += -DAEGISUB -Iinclude -I../libffms/include @WX_CPPFLAGS@ @OPENMP_CXXFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@
AM_CXXFLAGS += -DAEGISUB -Iinclude -I../libffms/include -I../libaegisub/include @WX_CPPFLAGS@ @OPENMP_CXXFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@
bin_PROGRAMS = aegisub-2.2
aegisub_2_2_LDADD = libresrc/libresrc.a $(libosxutil_lib)
aegisub_2_2_LDADD = libresrc/libresrc.a $(libosxutil_lib) -L../libaegisub -laegisub-2.2
aegisub_2_2_CPPFLAGS = @FREETYPE_CFLAGS@
aegisub_2_2_LDFLAGS = @DEBUG_FLAGS@ @PROFILE_FLAGS@ @GL_LIBS@ @PTHREAD_LIBS@ @WX_LIBS@ @ICONV_LDFLAGS@ $(libosxutil_ldflags) @CCMALLOC_LDFLAGS@ @EFENCE_LDFLAGS@
LIBS += @FREETYPE_LIBS@ @FONTCONFIG_LIBS@ @CCMALLOC_LIBS@
@ -222,6 +222,7 @@ aegisub_2_2_SOURCES = \
charset_conv.cpp \
colorspace.cpp \
colour_button.cpp \
compat.cpp \
dialog_about.cpp \
dialog_attachments.cpp \
dialog_automation.cpp \
@ -232,7 +233,6 @@ aegisub_2_2_SOURCES = \
dialog_fonts_collector.cpp \
dialog_jumpto.cpp \
dialog_kara_timing_copy.cpp \
dialog_options.cpp \
dialog_paste_over.cpp \
dialog_progress.cpp \
dialog_properties.cpp \
@ -274,6 +274,7 @@ aegisub_2_2_SOURCES = \
mythes.cxx \
options.cpp \
plugin_manager.cpp \
preferences.cpp \
scintilla_text_ctrl.cpp \
spellchecker.cpp \
spline.cpp \

View file

@ -243,10 +243,6 @@
#undef _CRT_SECURE_NO_WARNINGS
#endif
///////////////////
// Aegisub headers
#include "include/aegisub/exception.h"
#endif // C++
#endif // AGI_PRE_H

View file

@ -42,10 +42,9 @@
// Headers
#ifndef AGI_PRE
#include <wx/string.h>
#include "include/aegisub/exception.h"
#endif
#include <libaegisub/exception.h>
//////////////
// Prototypes
@ -81,18 +80,18 @@ namespace Aegisub {
/// @brief DOCME
///
/// DOCME
class InvalidMarginIdError : public InternalError {
class InvalidMarginIdError : public agi::InternalError {
public:
/// @brief DOCME
/// @return
///
InvalidMarginIdError() : InternalError(_T("Invalid margin id"), 0) { }
InvalidMarginIdError() : InternalError("Invalid margin id", 0) { }
/// @brief DOCME
/// @return
///
const wxChar *GetName() { return _T("internal_error/invalid_margin_id"); }
const char *GetName() { return "internal_error/invalid_margin_id"; }
};
};

View file

@ -50,6 +50,8 @@
#include "ass_file.h"
#include "ass_override.h"
#include "ass_style.h"
#include "compat.h"
#include "main.h"
#include "options.h"
#include "subtitle_format.h"
#include "text_file_reader.h"
@ -794,7 +796,7 @@ AssStyle *AssFile::GetStyle(wxString name) {
/// @brief Adds file name to list of recent
/// @param file
void AssFile::AddToRecent(wxString file) {
Options.AddToRecentList(file,_T("Recent sub"));
AegisubApp::Get()->mru->Add("Subtitle", STD_STR(file));
}
/// @brief List of supported wildcards
@ -861,7 +863,7 @@ void AssFile::StackPush(wxString desc) {
for (std::list<AssFile*>::iterator cur=UndoStack.begin();cur!=UndoStack.end();cur++) {
n++;
}
int depth = Options.AsInt(_T("Undo levels"));
int depth = OPT_GET("Limits/Undo Levels")->GetInt();
while (n > depth) {
delete UndoStack.front();
UndoStack.pop_front();

View file

@ -54,6 +54,7 @@
#include "frame_main.h"
#include "hotkeys.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "toggle_bitmap.h"
#include "tooltip_manager.h"
@ -97,7 +98,7 @@ wxPanel(parent,-1,wxDefaultPosition,wxDefaultSize,wxTAB_TRAVERSAL|wxBORDER_RAISE
VolumeBar = new wxSlider(this,Audio_Volume,50,0,100,wxDefaultPosition,wxSize(-1,20),wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE);
VolumeBar->PushEventHandler(new FocusEvent());
VolumeBar->SetToolTip(_("Audio Volume"));
bool link = Options.AsBool(_T("Audio Link"));
bool link = OPT_GET("Audio/Link")->GetBool();
if (link) {
VolumeBar->SetValue(VerticalZoom->GetValue());
VolumeBar->Enable(false);
@ -177,23 +178,23 @@ wxPanel(parent,-1,wxDefaultPosition,wxDefaultSize,wxTAB_TRAVERSAL|wxBORDER_RAISE
AutoCommit = new ToggleBitmap(this,Audio_Check_AutoCommit,GETIMAGE(toggle_audio_autocommit_24),wxSize(30,-1));
AutoCommit->SetToolTip(_("Automatically commit all changes"));
AutoCommit->SetValue(Options.AsBool(_T("Audio Autocommit")));
AutoCommit->SetValue(OPT_GET("Audio/Auto/Commit")->GetBool());
ButtonSizer->Add(AutoCommit,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,0);
NextCommit = new ToggleBitmap(this,Audio_Check_NextCommit,GETIMAGE(toggle_audio_nextcommit_24),wxSize(30,-1));
NextCommit->SetToolTip(_("Auto goes to next line on commit"));
NextCommit->SetValue(Options.AsBool(_T("Audio Next Line on Commit")));
NextCommit->SetValue(OPT_GET("Audio/Next Line on Commit")->GetBool());
ButtonSizer->Add(NextCommit,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,0);
AutoScroll = new ToggleBitmap(this,Audio_Check_AutoGoto,GETIMAGE(toggle_audio_autoscroll_24),wxSize(30,-1));
AutoScroll->SetToolTip(_("Auto scrolls audio display to selected line"));
AutoScroll->SetValue(Options.AsBool(_T("Audio Autoscroll")));
AutoScroll->SetValue(OPT_GET("Audio/Auto/Scroll")->GetBool());
ButtonSizer->Add(AutoScroll,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,0);
SpectrumMode = new ToggleBitmap(this,Audio_Check_Spectrum,GETIMAGE(toggle_audio_spectrum_24),wxSize(30,-1));
SpectrumMode->SetToolTip(_("Spectrum analyzer mode"));
SpectrumMode->SetValue(Options.AsBool(_T("Audio Spectrum")));
SpectrumMode->SetValue(OPT_GET("Audio/Spectrum")->GetBool());
ButtonSizer->Add(SpectrumMode,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,0);
MedusaMode = new ToggleBitmap(this,Audio_Check_Medusa,GETIMAGE(toggle_audio_medusa_24),wxSize(30,-1));
MedusaMode->SetToolTip(_("Enable Medusa-Style Timing Shortcuts"));
MedusaMode->SetValue(Options.AsBool(_T("Audio Medusa Timing Hotkeys")));
MedusaMode->SetValue(OPT_GET("Audio/Medusa Timing Hotkeys")->GetBool());
ButtonSizer->Add(MedusaMode,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,0);
ButtonSizer->AddStretchSpacer(1);
@ -383,8 +384,7 @@ void AudioBox::OnVerticalLink(wxCommandEvent &event) {
}
VolumeBar->Enable(!VerticalLink->GetValue());
Options.SetBool(_T("Audio Link"),VerticalLink->GetValue());
Options.Save();
OPT_SET("Audio/Link")->SetBool(VerticalLink->GetValue());
}
@ -419,8 +419,7 @@ void AudioBox::OnSash(wxSashEvent& event) {
Sash->GetParent()->Layout();
// Store new size
Options.SetInt(_T("Audio Display Height"),h);
Options.Save();
OPT_SET("Audio/Display Height")->SetInt(h);
// Fix layout
frameMain->Freeze();
@ -683,8 +682,7 @@ void AudioBox::OnGoto(wxCommandEvent &event) {
///
void AudioBox::OnAutoGoto(wxCommandEvent &event) {
audioDisplay->SetFocus();
Options.SetBool(_T("Audio Autoscroll"),AutoScroll->GetValue());
Options.Save();
OPT_SET("Audio/Auto/Scroll")->SetBool(AutoScroll->GetValue());
}
@ -694,8 +692,7 @@ void AudioBox::OnAutoGoto(wxCommandEvent &event) {
///
void AudioBox::OnAutoCommit(wxCommandEvent &event) {
audioDisplay->SetFocus();
Options.SetBool(_T("Audio Autocommit"),AutoCommit->GetValue());
Options.Save();
OPT_SET("Audio/Auto/Commit")->SetBool(AutoCommit->GetValue());
}
@ -705,8 +702,7 @@ void AudioBox::OnAutoCommit(wxCommandEvent &event) {
///
void AudioBox::OnNextLineCommit(wxCommandEvent &event) {
audioDisplay->SetFocus();
Options.SetBool(_T("Audio Next Line on Commit"),NextCommit->GetValue());
Options.Save();
OPT_SET("Audio/Next Line on Commit")->SetBool(NextCommit->GetValue());
}
@ -716,8 +712,7 @@ void AudioBox::OnNextLineCommit(wxCommandEvent &event) {
///
void AudioBox::OnMedusaMode(wxCommandEvent &event) {
audioDisplay->SetFocus();
Options.SetBool(_T("Audio Medusa Timing Hotkeys"),MedusaMode->GetValue());
Options.Save();
OPT_SET("Audio/Medusa Timing Hotkeys")->SetBool(MedusaMode->GetValue());
frameMain->SetAccelerators();
}
@ -727,8 +722,7 @@ void AudioBox::OnMedusaMode(wxCommandEvent &event) {
/// @param event
///
void AudioBox::OnSpectrumMode(wxCommandEvent &event) {
Options.SetBool(_T("Audio Spectrum"),SpectrumMode->GetValue());
Options.Save();
OPT_SET("Audio/Spectrum")->SetBool(SpectrumMode->GetValue());
audioDisplay->UpdateImage(false);
audioDisplay->SetFocus();
audioDisplay->Refresh(false);

View file

@ -55,8 +55,10 @@
#endif
#include "audio_provider_stream.h"
#include "colorspace.h"
#include "compat.h"
#include "fft.h"
#include "hotkeys.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "subs_edit_box.h"
@ -79,7 +81,7 @@
/// @brief Constructor
/// @param parent
AudioDisplay::AudioDisplay(wxWindow *parent)
: wxWindow (parent, -1, wxDefaultPosition, wxSize(200,Options.AsInt(_T("Audio Display Height"))), AudioDisplayWindowStyle , _T("Audio Display"))
: wxWindow (parent, -1, wxDefaultPosition, wxSize(200,OPT_GET("Audio/Display Height")->GetInt()), AudioDisplayWindowStyle , _T("Audio Display"))
{
// Set variables
origImage = NULL;
@ -118,7 +120,7 @@ AudioDisplay::AudioDisplay(wxWindow *parent)
// Init
UpdateTimer.SetOwner(this,Audio_Update_Timer);
GetClientSize(&w,&h);
h -= Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
SetSamplesPercent(50,false);
// Set cursor
@ -188,7 +190,7 @@ void AudioDisplay::DoUpdateImage() {
bool weak = needImageUpdateWeak;
// Prepare bitmap
int timelineHeight = Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
int timelineHeight = OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
int displayH = h+timelineHeight;
if (origImage) {
if (origImage->GetWidth() != w || origImage->GetHeight() != displayH) {
@ -198,9 +200,9 @@ void AudioDisplay::DoUpdateImage() {
}
// Options
bool draw_boundary_lines = Options.AsBool(_T("Audio Draw Secondary Lines"));
bool draw_selection_background = Options.AsBool(_T("Audio Draw Selection Background"));
bool drawKeyframes = Options.AsBool(_T("Audio Draw Keyframes"));
bool draw_boundary_lines = OPT_GET("Audio/Display/Draw/Secondary Lines")->GetBool();
bool draw_selection_background = OPT_GET("Audio/Display/Draw/Selection Background")->GetBool();
bool drawKeyframes = OPT_GET("Audio/Display/Draw/Keyframes")->GetBool();
// Invalid dimensions
if (w == 0 || displayH == 0) return;
@ -210,7 +212,7 @@ void AudioDisplay::DoUpdateImage() {
// Is spectrum?
bool spectrum = false;
if (provider && Options.AsBool(_T("Audio Spectrum"))) {
if (provider && OPT_GET("Audio/Spectrum")->GetBool()) {
spectrum = true;
}
@ -220,7 +222,7 @@ void AudioDisplay::DoUpdateImage() {
// Black background
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Background"))));
dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Background/Background")->GetColour())));
dc.DrawRectangle(0,0,w,h);
// Selection position
@ -254,8 +256,8 @@ void AudioDisplay::DoUpdateImage() {
// Draw selection bg
if (hasSel && drawSelStart < drawSelEnd && draw_selection_background) {
if (NeedCommit && !karaoke->enabled) dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Selection Background Modified"))));
else dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Selection Background"))));
if (NeedCommit && !karaoke->enabled) dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Background/Selection Modified")->GetColour())));
else dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Background/Background")->GetColour())));
dc.DrawRectangle(drawSelStart,0,drawSelEnd-drawSelStart,h);
}
@ -279,7 +281,7 @@ void AudioDisplay::DoUpdateImage() {
int64_t start = Position*samples;
int rate = provider->GetSampleRate();
int pixBounds = rate / samples;
dc.SetPen(wxPen(Options.AsColour(_T("Audio Seconds Boundaries")),1,wxDOT));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Seconds Boundaries")->GetColour()),1,wxDOT));
if (pixBounds >= 8) {
for (int x=0;x<w;x++) {
if (((x*samples)+start) % rate < samples) {
@ -290,9 +292,9 @@ void AudioDisplay::DoUpdateImage() {
}
// Draw current frame
if (Options.AsBool(_T("Audio Draw Video Position"))) {
if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool()) {
if (VideoContext::Get()->IsLoaded()) {
dc.SetPen(wxPen(Options.AsColour(_T("Audio Play Cursor")),2,wxLONG_DASH));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Play Cursor")->GetColour())));
int x = GetXAtMS(VFR_Output.GetTimeAtFrame(VideoContext::Get()->GetFrameN()));
dc.DrawLine(x,0,x,h);
}
@ -310,9 +312,9 @@ void AudioDisplay::DoUpdateImage() {
// Draw boundaries
if (true) {
// Draw start boundary
int selWidth = Options.AsInt(_T("Audio Line boundaries Thickness"));
dc.SetPen(wxPen(Options.AsColour(_T("Audio Line boundary start"))));
dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Line boundary start"))));
int selWidth = OPT_GET("Audio/Line Boundaries Thickness")->GetInt();
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Line boundary Start")->GetColour())));
dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Line boundary Start")->GetColour())));
dc.DrawRectangle(lineStart-selWidth/2+1,0,selWidth,h);
wxPoint points1[3] = { wxPoint(lineStart,0), wxPoint(lineStart+10,0), wxPoint(lineStart,10) };
wxPoint points2[3] = { wxPoint(lineStart,h-1), wxPoint(lineStart+10,h-1), wxPoint(lineStart,h-11) };
@ -320,8 +322,8 @@ void AudioDisplay::DoUpdateImage() {
dc.DrawPolygon(3,points2);
// Draw end boundary
dc.SetPen(wxPen(Options.AsColour(_T("Audio Line boundary end"))));
dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Line boundary end"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Line boundary End")->GetColour())));
dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Line boundary End")->GetColour())));
dc.DrawRectangle(lineEnd-selWidth/2+1,0,selWidth,h);
wxPoint points3[3] = { wxPoint(lineEnd,0), wxPoint(lineEnd-10,0), wxPoint(lineEnd,10) };
wxPoint points4[3] = { wxPoint(lineEnd,h-1), wxPoint(lineEnd-10,h-1), wxPoint(lineEnd,h-11) };
@ -333,11 +335,11 @@ void AudioDisplay::DoUpdateImage() {
if (hasKaraoke) {
try {
// Prepare
wxPen curPen(Options.AsColour(_T("Audio Syllable boundaries")),1,wxDOT);
wxPen curPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Syllable Boundaries")->GetColour()),1,wxDOT);
dc.SetPen(curPen);
wxFont curFont(9,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Verdana"),wxFONTENCODING_SYSTEM);
dc.SetFont(curFont);
if (!spectrum) dc.SetTextForeground(Options.AsColour(_T("Audio Syllable text")));
if (!spectrum) dc.SetTextForeground(lagi_wxColour(OPT_GET("Colour/Audio Display/Syllable Text")->GetColour()));
else dc.SetTextForeground(wxColour(255,255,255));
size_t karn = karaoke->syllables.size();
int64_t pos1,pos2;
@ -403,18 +405,18 @@ void AudioDisplay::DoUpdateImage() {
/// Draws markers for inactive lines, eg. the previous line, per configuration.
void AudioDisplay::DrawInactiveLines(wxDC &dc) {
// Check if there is anything to do
int shadeType = Options.AsInt(_T("Audio Inactive Lines Display Mode"));
int shadeType = OPT_GET("Audio/Inactive Lines Display Mode")->GetInt();
if (shadeType == 0) return;
// Spectrum?
bool spectrum = false;
if (provider && Options.AsBool(_T("Audio Spectrum"))) {
if (provider && OPT_GET("Audio/Spectrum")->GetBool()) {
spectrum = true;
}
// Set options
dc.SetBrush(wxBrush(Options.AsColour(_T("Audio Line boundary inactive line"))));
int selWidth = Options.AsInt(_T("Audio Line boundaries Thickness"));
dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Audio Display/Line Boundary Inactive Line")->GetColour())));
int selWidth = OPT_GET("Audio/Line Boundaries Thickness")->GetInt();
AssDialogue *shade;
int shadeX1,shadeX2;
int shadeFrom,shadeTo;
@ -459,13 +461,13 @@ void AudioDisplay::DrawInactiveLines(wxDC &dc) {
x2 = MIN(x2,selX1);
// Set pen and draw
dc.SetPen(wxPen(Options.AsColour(_T("Audio Waveform Inactive"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Waveform Inactive")->GetColour())));
for (int i=x1;i<x2;i++) dc.DrawLine(i,peak[i],i,min[i]-1);
for (int i=x3;i<x4;i++) dc.DrawLine(i,peak[i],i,min[i]-1);
}
// Draw boundaries
dc.SetPen(wxPen(Options.AsColour(_T("Audio Line boundary inactive line"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Line Boundary Inactive Line")->GetColour())));
dc.DrawRectangle(shadeX1-selWidth/2+1,0,selWidth,h);
dc.DrawRectangle(shadeX2-selWidth/2+1,0,selWidth,h);
}
@ -498,7 +500,7 @@ void AudioDisplay::DrawKeyframes(wxDC &dc) {
/// @param dc The DC to draw to.
void AudioDisplay::DrawTimescale(wxDC &dc) {
// Set size
int timelineHeight = Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
int timelineHeight = OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
// Set colours
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
@ -577,23 +579,23 @@ void AudioDisplay::DrawWaveform(wxDC &dc,bool weak) {
// Draw pre-selection
if (!hasSel) selStartCap = w;
dc.SetPen(wxPen(Options.AsColour(_T("Audio Waveform"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Waveform")->GetColour())));
for (int64_t i=0;i<selStartCap;i++) {
dc.DrawLine(i,peak[i],i,min[i]-1);
}
if (hasSel) {
// Draw selection
if (Options.AsBool(_T("Audio Draw Selection Background"))) {
if (NeedCommit && !karaoke->enabled) dc.SetPen(wxPen(Options.AsColour(_T("Audio Waveform Modified"))));
else dc.SetPen(wxPen(Options.AsColour(_T("Audio Waveform Selected"))));
if (OPT_GET("Audio/Display/Draw/Selection Background")->GetBool()) {
if (NeedCommit && !karaoke->enabled) dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Waveform Modified")->GetColour())));
else dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Waveform Selected")->GetColour())));
}
for (int64_t i=selStartCap;i<selEndCap;i++) {
dc.DrawLine(i,peak[i],i,min[i]-1);
}
// Draw post-selection
dc.SetPen(wxPen(Options.AsColour(_T("Audio Waveform"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Waveform")->GetColour())));
for (int64_t i=selEndCap;i<w;i++) {
dc.DrawLine(i,peak[i],i,min[i]-1);
}
@ -707,7 +709,7 @@ void AudioDisplay::GetKaraokePos(int64_t &karStart,int64_t &karEnd, bool cap) {
void AudioDisplay::Update() {
if (blockUpdate) return;
if (loaded) {
if (Options.AsBool(_T("Audio Autoscroll")))
if (OPT_GET("Audio/Auto/Scroll")->GetBool())
MakeDialogueVisible();
else
UpdateImage(true);
@ -717,7 +719,7 @@ void AudioDisplay::Update() {
/// @brief Recreate the image
void AudioDisplay::RecreateImage() {
GetClientSize(&w,&h);
h -= Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
delete origImage;
origImage = NULL;
UpdateImage(false);
@ -919,7 +921,7 @@ void AudioDisplay::SetFile(wxString file) {
// Add to recent
if (!is_dummy) {
wxLogDebug(_T("AudioDisplay::SetFile: add to recent"));
Options.AddToRecentList(file,_T("Recent aud"));
AegisubApp::Get()->mru->Add("Audio", STD_STR(file));
wxFileName fn(file);
StandardPaths::SetPathValue(_T("?audio"),fn.GetPath());
}
@ -1140,7 +1142,7 @@ void AudioDisplay::SetDialogue(SubtitlesGrid *_grid,AssDialogue *diag,int n) {
NeedCommit = false;
// Set times
if (dialogue && !dontReadTimes && Options.AsBool(_T("Audio grab times on select"))) {
if (dialogue && !dontReadTimes && OPT_GET("Audio/Grab Times on Select")->GetBool()) {
wxLogDebug(_T("AudioDisplay::SetDialogue: grabbing times"));
int s = dialogue->Start.GetMS();
int e = dialogue->End.GetMS();
@ -1249,7 +1251,7 @@ void AudioDisplay::CommitChanges (bool nextLine) {
}
// Next line (ugh what a condition, can this be simplified?)
if (nextLine && !karaoke->enabled && Options.AsBool(_T("Audio Next Line on Commit")) && !wasKaraSplitting) {
if (nextLine && !karaoke->enabled && OPT_GET("Audio/Next Line on Commit")->GetBool() && !wasKaraSplitting) {
wxLogDebug(_T("AudioDisplay::CommitChanges: going to next line"));
// Insert a line if it doesn't exist
int nrows = grid->GetRows();
@ -1258,15 +1260,15 @@ void AudioDisplay::CommitChanges (bool nextLine) {
AssDialogue *def = new AssDialogue;
def->Start = grid->GetDialogue(line_n)->End;
def->End = grid->GetDialogue(line_n)->End;
def->End.SetMS(def->End.GetMS()+Options.AsInt(_T("Timing Default Duration")));
def->End.SetMS(def->End.GetMS()+OPT_GET("Timing/Default Duration")->GetInt());
def->Style = grid->GetDialogue(line_n)->Style;
grid->InsertLine(def,line_n,true);
curStartMS = curEndMS;
curEndMS = curStartMS + Options.AsInt(_T("Timing Default Duration"));
curEndMS = curStartMS + OPT_GET("Timing/Default Duration")->GetInt();
}
else if (grid->GetDialogue(line_n+1)->Start.GetMS() == 0 && grid->GetDialogue(line_n+1)->End.GetMS() == 0) {
curStartMS = curEndMS;
curEndMS = curStartMS + Options.AsInt(_T("Timing Default Duration"));
curEndMS = curStartMS + OPT_GET("Timing/Default Duration")->GetInt();
}
else {
curStartMS = grid->GetDialogue(line_n+1)->Start.GetMS();
@ -1289,19 +1291,19 @@ void AudioDisplay::CommitChanges (bool nextLine) {
void AudioDisplay::AddLead(bool in,bool out) {
// Lead in
if (in) {
curStartMS -= Options.AsInt(_T("Audio Lead in"));
curStartMS -= OPT_GET("Audio/Lead/IN")->GetInt();
if (curStartMS < 0) curStartMS = 0;
}
// Lead out
if (out) {
curEndMS += Options.AsInt(_T("Audio Lead out"));
curEndMS += OPT_GET("Audio/Lead/OUT")->GetInt();
}
// Set changes
UpdateTimeEditCtrls();
NeedCommit = true;
if (Options.AsBool(_T("Audio Autocommit"))) CommitChanges();
if (OPT_GET("Audio/Auto/Commit")->GetBool()) CommitChanges();
Update();
}
@ -1337,7 +1339,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
int64_t y = event.GetY();
bool karMode = karaoke->enabled;
bool shiftDown = event.m_shiftDown;
int timelineHeight = Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
int timelineHeight = OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
// Leaving event
if (event.Leaving()) {
@ -1358,7 +1360,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
inside = true;
// Get focus
if (wxWindow::FindFocus() != this && Options.AsBool(_T("Audio Autofocus"))) SetFocus();
if (wxWindow::FindFocus() != this && OPT_GET("Audio/Auto/Focus")->GetBool()) SetFocus();
}
else if (y < h+timelineHeight) onScale = true;
}
@ -1387,7 +1389,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
if (event.GetWheelRotation() != 0) {
// Zoom or scroll?
bool zoom = shiftDown;
if (Options.AsBool(_T("Audio Wheel Default To Zoom"))) zoom = !zoom;
if (OPT_GET("Audio/Wheel Default to Zoom")->GetBool()) zoom = !zoom;
// Zoom
if (zoom) {
@ -1423,7 +1425,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
dc.DrawLine(x,0,x,h);
// Time
if (Options.AsBool(_T("Audio Draw Cursor Time"))) {
if (OPT_GET("Audio/Display/Draw/Cursor")->GetBool()) {
// Time string
AssTime time;
time.SetMS(GetMSAtX(x));
@ -1525,7 +1527,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
// Line timing mode
if (!karTime) {
// Grab start
if (abs64 (x - selStart) < 6 && Options.AsBool(_T("Disable Dragging Times"))==false) {
if (abs64 (x - selStart) < 6 && OPT_GET("Audio/Display/Dragging Times")->GetBool()==false) {
wxCursor cursor(wxCURSOR_SIZEWE);
SetCursor(cursor);
defCursor = false;
@ -1536,7 +1538,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
}
// Grab end
else if (abs64 (x - selEnd) < 6 && Options.AsBool(_T("Disable Dragging Times"))==false) {
else if (abs64 (x - selEnd) < 6 && OPT_GET("Audio/Display/Dragging Times")->GetBool()==false) {
wxCursor cursor(wxCURSOR_SIZEWE);
SetCursor(cursor);
defCursor = false;
@ -1608,7 +1610,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
updated = true;
diagUpdated = true;
if (leftIsDown && abs((long)(x-lastX)) > Options.AsInt(_T("Audio Start Drag Sensitivity"))) {
if (leftIsDown && abs((long)(x-lastX)) > OPT_GET("Audio/Start Drag Sensitivity")->GetInt()) {
selStart = lastX;
selEnd = x;
curStartMS = GetBoundarySnap(GetMSAtX(lastX),10,event.ShiftDown(),true);
@ -1697,7 +1699,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) {
NeedCommit = true;
if (curStartMS <= curEndMS) {
UpdateTimeEditCtrls();
if (Options.AsBool(_T("Audio Autocommit"))) CommitChanges();
if (OPT_GET("Audio/Auto/Commit")->GetBool()) CommitChanges();
}
else UpdateImage(true);
@ -1750,9 +1752,9 @@ int AudioDisplay::GetBoundarySnap(int ms,int rangeX,bool shiftHeld,bool start) {
// Keyframe boundaries
wxArrayInt boundaries;
bool snapKey = Options.AsBool(_T("Audio snap to keyframes"));
bool snapKey = OPT_GET("Audio/Display/Snap/Keyframes")->GetBool();
if (shiftHeld) snapKey = !snapKey;
if (snapKey && VideoContext::Get()->KeyFramesLoaded() && Options.AsBool(_T("Audio Draw Keyframes"))) {
if (snapKey && VideoContext::Get()->KeyFramesLoaded() && OPT_GET("Audio/Display/Draw/Keyframes")->GetBool()) {
int64_t keyMS;
wxArrayInt keyFrames = VideoContext::Get()->GetKeyFrames();
int frame;
@ -1767,8 +1769,8 @@ int AudioDisplay::GetBoundarySnap(int ms,int rangeX,bool shiftHeld,bool start) {
}
// Other subtitles' boundaries
int inactiveType = Options.AsInt(_T("Audio Inactive Lines Display Mode"));
bool snapLines = Options.AsBool(_T("Audio snap to other lines"));
int inactiveType = OPT_GET("Audio/Inactive Lines Display Mode")->GetInt();
bool snapLines = OPT_GET("Audio/Display/Snap/Other Lines")->GetBool();
if (shiftHeld) snapLines = !snapLines;
if (snapLines && (inactiveType == 1 || inactiveType == 2)) {
AssDialogue *shade;
@ -1932,7 +1934,7 @@ int AudioDisplay::GetBoundarySnap(int ms,int rangeX,bool shiftHeld,bool start) {
void AudioDisplay::OnSize(wxSizeEvent &event) {
// Set size
GetClientSize(&w,&h);
h -= Options.AsBool(_T("Audio Draw Timeline")) ? 20 : 0;
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
// Update image
UpdateSamples();
@ -1973,7 +1975,7 @@ void AudioDisplay::OnUpdateTimer(wxTimerEvent &event) {
int posX = GetXAtSample(curPos);
bool fullDraw = false;
bool centerLock = false;
bool scrollToCursor = Options.AsBool(_T("Audio lock scroll on cursor"));
bool scrollToCursor = OPT_GET("Audio/Lock Scroll on Cursor")->GetBool();
if (centerLock) {
int goTo = MAX(0,curPos - w*samples/2);
if (goTo >= 0) {
@ -1999,7 +2001,7 @@ void AudioDisplay::OnUpdateTimer(wxTimerEvent &event) {
wxMemoryDC src;
curpos = GetXAtSample(curPos);
if (curpos >= 0 && curpos < GetClientSize().GetWidth()) {
dc.SetPen(wxPen(Options.AsColour(_T("Audio Play cursor"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Audio Display/Play Cursor")->GetColour())));
src.SelectObject(*origImage);
if (fullDraw) {
//dc.Blit(0,0,w,h,&src,0,0);
@ -2195,7 +2197,7 @@ void AudioDisplay::OnKeyDown(wxKeyEvent &event) {
if (diagUpdated) {
diagUpdated = false;
NeedCommit = true;
if (Options.AsBool(_T("Audio Autocommit")) && curStartMS <= curEndMS) CommitChanges();
if (OPT_GET("Audio/Auto/Commit")->GetBool() && curStartMS <= curEndMS) CommitChanges();
else UpdateImage(true);
}
}

View file

@ -59,6 +59,8 @@
#ifdef WITH_PULSEAUDIO
#include "audio_player_pulse.h"
#endif
#include "compat.h"
#include "main.h"
#include "options.h"
@ -151,7 +153,7 @@ void AudioPlayer::OnStopAudio(wxCommandEvent &event) {
///
AudioPlayer* AudioPlayerFactoryManager::GetAudioPlayer() {
// List of providers
wxArrayString list = GetFactoryList(Options.AsText(_T("Audio player")));
wxArrayString list = GetFactoryList(lagi_wxString(OPT_GET("Audio/Player")->GetString()));
// None available
if (list.Count() == 0) throw _T("No audio players are available.");

View file

@ -85,7 +85,7 @@ void AlsaPlayer::OpenStream()
// We want playback
stream = SND_PCM_STREAM_PLAYBACK;
// And get a device name
wxString device = Options.AsText(_T("Audio Alsa Device"));
wxString device = lagi_wxString(OPT_GET("Player/Audio/ALSA/Device")->GetString());
// Open device for blocking access
if (snd_pcm_open(&pcm_handle, device.mb_str(wxConvUTF8), stream, 0) < 0) { // supposedly we don't want SND_PCM_ASYNC even for async playback

View file

@ -863,8 +863,8 @@ DirectSoundPlayer2::DirectSoundPlayer2()
thread = 0;
// The buffer will hold BufferLength times WantedLatency milliseconds of audio
WantedLatency = Options.AsInt(_T("Audio dsound buffer latency"));
BufferLength = Options.AsInt(_T("Audio dsound buffer length"));
WantedLatency = OPT_GET("Player/Audio/DirectSound/Buffer Latency")->GetInt();
BufferLength = OPT_GET("Player/Audio/DirectSound/Buffer Length")->GetInt();
// sanity checking
if (WantedLatency <= 0)

View file

@ -43,6 +43,8 @@
#include "audio_player_oss.h"
#include "audio_provider_manager.h"
#include "frame_main.h"
#include "compat.h"
#include "main.h"
#include "options.h"
#include "utils.h"
@ -81,7 +83,7 @@ void OSSPlayer::OpenStream()
bpf = provider->GetChannels() * provider->GetBytesPerSample();
// Open device
wxString device = Options.AsText(_T("Audio OSS Device"));
wxString device = lagi_wxString(OPT_GET("Audio/OSS/Device")->GetString());
dspdev = ::open(device.mb_str(wxConvUTF8), O_WRONLY, 0);
if (dspdev < 0) {
throw _T("OSS player: opening device failed");

View file

@ -44,6 +44,7 @@
#include "audio_player_portaudio.h"
#include "audio_provider_manager.h"
#include "charset_conv.h"
#include "main.h"
#include "options.h"
#include "utils.h"
#include <wx/log.h>
@ -84,7 +85,7 @@ void PortAudioPlayer::OpenStream() {
// Open stream
PaStreamParameters pa_output_p;
int pa_config_default = Options.AsInt(_T("Audio PortAudio Device"));
int pa_config_default = OPT_GET("Player/Audio/PortAudio/Device")->GetInt();
PaDeviceIndex pa_device;
if (pa_config_default < 0) {

View file

@ -57,6 +57,8 @@
#include "audio_provider_quicktime.h"
#endif
#include "audio_provider_ram.h"
#include "compat.h"
#include "main.h"
#include "options.h"
@ -243,7 +245,7 @@ AudioProvider *AudioProviderFactoryManager::GetAudioProvider(wxString filename,
// Prepare provider
AudioProvider *provider = NULL;
if (!Options.AsBool(_T("Audio Disable PCM Provider"))) {
if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) {
// Try a PCM provider first
provider = CreatePCMAudioProvider(filename);
if (provider) {
@ -257,7 +259,7 @@ AudioProvider *AudioProviderFactoryManager::GetAudioProvider(wxString filename,
}
// List of providers
wxArrayString list = GetFactoryList(Options.AsText(_T("Audio provider")));
wxArrayString list = GetFactoryList(lagi_wxString(OPT_GET("Audio/Provider")->GetString()));
// None available
if (list.Count() == 0) throw _T("No audio providers are available.");
@ -285,7 +287,7 @@ AudioProvider *AudioProviderFactoryManager::GetAudioProvider(wxString filename,
provider = CreateConvertAudioProvider(provider);
// Change provider to RAM/HD cache if needed
if (cache == -1) cache = Options.AsInt(_T("Audio Cache"));
if (cache == -1) cache = OPT_GET("Audio/Cache/Type")->GetInt();
if (cache) {
AudioProvider *final = NULL;

View file

@ -51,6 +51,8 @@
#include "audio_provider_avs.h"
#include "charset_conv.h"
#include "compat.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "utils.h"
@ -152,7 +154,7 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
// Convert to one channel
char buffer[1024];
strcpy(buffer,Options.AsText(_T("Audio Downmixer")).mb_str(csConvLocal));
strcpy(buffer,lagi_wxString(OPT_GET("Audio/Downmixer")->GetString()).mb_str(csConvLocal));
script = env->Invoke(buffer, _clip);
// Convert to 16 bits per sample
@ -160,7 +162,7 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
vi = script.AsClip()->GetVideoInfo();
// Convert sample rate
int setsample = Options.AsInt(_T("Audio Sample Rate"));
int setsample = OPT_GET("Provider/Audio/AVS/Sample Rate")->GetInt();
if (vi.SamplesPerSecond() < 32000) setsample = 44100;
if (setsample != 0) {
AVSValue args[2] = { script, setsample };

View file

@ -50,6 +50,7 @@
#include "audio_provider_ffmpegsource.h"
#include "include/aegisub/aegisub.h"
#include "main.h"
#include "options.h"
@ -164,7 +165,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
// moment of truth
if (!IndexIsValid) {
int TrackMask;
if (Options.AsBool(_T("FFmpegSource always index all tracks")) || TrackNumber == FFMS_TRACKMASK_ALL)
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() || TrackNumber == FFMS_TRACKMASK_ALL)
TrackMask = FFMS_TRACKMASK_ALL;
else
TrackMask = (1 << TrackNumber);

View file

@ -47,6 +47,7 @@
#endif
#include "audio_provider_hd.h"
#include "compat.h"
#include "dialog_progress.h"
#include "frame_main.h"
#include "main.h"
@ -159,7 +160,7 @@ void HDAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
///
wxString HDAudioProvider::DiskCachePath() {
// Default
wxString path = Options.AsText(_T("Audio HD Cache Location"));
wxString path = lagi_wxString(OPT_GET("Audio/Cache/HD/Location")->GetString());
if (path == _T("default")) return StandardPaths::DecodePath(_T("?temp/"));
// Specified
@ -172,7 +173,7 @@ wxString HDAudioProvider::DiskCachePath() {
///
wxString HDAudioProvider::DiskCacheName() {
// Get pattern
wxString pattern = Options.AsText(_T("Audio HD Cache Name"));
wxString pattern = lagi_wxString(OPT_GET("Audio/Cache/HD/Name")->GetString());
if (pattern.Find(_T("%02i")) == wxNOT_FOUND) pattern = _T("audio%02i.tmp");
// Try from 00 to 99

View file

@ -54,6 +54,7 @@
#include "audio_renderer_spectrum.h"
#include "colorspace.h"
#include "fft.h"
#include "main.h"
#include "options.h"
#include "utils.h"
@ -565,7 +566,7 @@ public:
cache_root = new IntermediateSpectrumCache(provider, 0, num_lines, num_overlaps, 0);
// option is stored in megabytes, but we want number of bytes
unsigned long max_cache_size = Options.AsInt(_T("Audio Spectrum Memory Max"));
unsigned long max_cache_size = OPT_GET("Audio/Renderer/Spectrum/Memory Max")->GetInt();
// It can't go too low
if (max_cache_size < 5) max_cache_size = 128;
max_cache_size *= 1024 * 1024;
@ -590,7 +591,7 @@ AudioSpectrum::AudioSpectrum(AudioProvider *_provider)
provider = _provider;
// Determine the quality of the spectrum rendering based on an index
int quality_index = Options.AsInt(_T("Audio Spectrum Quality"));
int quality_index = OPT_GET("Audio/Renderer/Spectrum/Quality")->GetInt();
if (quality_index < 0) quality_index = 0;
if (quality_index > 5) quality_index = 5; // no need to go freaking insane
@ -655,7 +656,7 @@ AudioSpectrum::AudioSpectrum(AudioProvider *_provider)
cache = new AudioSpectrumCacheManager(provider, line_length, num_lines, fft_overlaps);
power_scale = 1;
minband = Options.AsInt(_T("Audio Spectrum Cutoff"));
minband = OPT_GET("Audio/Renderer/Spectrum/Cutoff")->GetInt();
maxband = line_length - minband * 2/3; // TODO: make this customisable?
// Generate colour maps

View file

@ -68,6 +68,8 @@
#include "ass_file.h"
#include "ass_style.h"
#include "auto4_base.h"
#include "compat.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "string_codec.h"
@ -491,7 +493,7 @@ namespace Automation4 {
Center();
// Init trace level
trace_level = Options.AsInt(_T("Automation Trace Level"));
trace_level = OPT_GET("Automation/Trace Level")->GetInt();
}
@ -678,7 +680,7 @@ namespace Automation4 {
// copied from auto3
include_path.clear();
include_path.EnsureFileAccessible(filename);
wxStringTokenizer toker(Options.AsText(_T("Automation Include Path")), _T("|"), wxTOKEN_STRTOK);
wxStringTokenizer toker(lagi_wxString(OPT_GET("Path/Automation/Include")->GetString()), _T("|"), wxTOKEN_STRTOK);
while (toker.HasMoreTokens()) {
// todo? make some error reporting here
wxFileName path(StandardPaths::DecodePath(toker.GetNextToken()));

View file

@ -58,6 +58,7 @@
#include "auto4_lua.h"
#include "auto4_lua_factory.h"
#include "auto4_lua_scriptreader.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "text_file_reader.h"
@ -196,7 +197,7 @@ namespace Automation4 {
lua_pushstring(L, "path");
lua_gettable(L, -3);
wxStringTokenizer toker(Options.AsText(_T("Automation Include Path")), _T("|"), wxTOKEN_STRTOK);
wxStringTokenizer toker(lagi_wxString(OPT_GET("Path/Automation/Include")->GetString()), _T("|"), wxTOKEN_STRTOK);
while (toker.HasMoreTokens()) {
wxFileName path(StandardPaths::DecodePath(toker.GetNextToken()));
if (path.IsOk() && !path.IsRelative() && path.DirExists()) {
@ -563,7 +564,7 @@ namespace Automation4 {
, nargs(_nargs)
, nresults(_nresults)
{
int prio = Options.AsInt(_T("Automation Thread Priority"));
int prio = OPT_GET("Automation/Lua/Thread Priority")->GetInt();
if (prio == 0) prio = 50; // normal
else if (prio == 1) prio = 30; // below normal
else if (prio == 2) prio = 10; // lowest

View file

@ -42,6 +42,7 @@
#include <wx/thread.h>
#endif
#include "compat.h"
#include "auto4_base.h"
#ifdef __WINDOWS__

View file

@ -42,6 +42,7 @@
#ifdef WITH_AVISYNTH
#include "avisynth_wrap.h"
#include "main.h"
#include "options.h"
#ifdef DEBUG_AVISYNTH_CODE
@ -101,7 +102,7 @@ AviSynthWrapper::AviSynthWrapper() {
AVSTRACE(_T("Got address of CreateScriptEnv"));
// Require Avisynth 2.5.6+?
if (Options.AsBool(_T("Allow Ancient Avisynth")))
if (OPT_GET("Provider/Avisynth/Allow Ancient")->GetBool())
env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION-1);
else
env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION);
@ -112,7 +113,7 @@ AviSynthWrapper::AviSynthWrapper() {
}
AVSTRACE(_T("Created script environment"));
// Set memory limit
int memoryMax = Options.AsInt(_T("Avisynth MemoryMax"));
const int memoryMax = OPT_GET("Provider/Avisynth/Memory Max")->GetInt();
if (memoryMax != 0) {
env->SetMemoryMax(memoryMax);
AVSTRACE(_T("Set Avisynth memory limit"));

View file

@ -48,7 +48,9 @@
#include "ass_style.h"
#include "audio_display.h"
#include "base_grid.h"
#include "compat.h"
#include "frame_main.h"
#include "main.h"
#include "options.h"
#include "subs_edit_box.h"
#include "utils.h"
@ -106,10 +108,10 @@ BaseGrid::~BaseGrid() {
///
void BaseGrid::UpdateStyle() {
// Set font
wxString fontname = Options.AsText(_T("Grid Font Face"));
wxString fontname = lagi_wxString(OPT_GET("Subtitle/Grid/Font Face")->GetString());
if (fontname.IsEmpty()) fontname = _T("Tahoma");
font.SetFaceName(fontname);
font.SetPointSize(Options.AsInt(_T("Grid font size")));
font.SetPointSize(OPT_GET("Subtitle/Grid/Font Size")->GetInt());
font.SetWeight(wxFONTWEIGHT_NORMAL);
// Set line height
@ -122,7 +124,9 @@ void BaseGrid::UpdateStyle() {
}
// Set column widths
for (int i=0;i<10;i++) showCol[i] = Options.AsBool(_T("Grid show column ") + AegiIntegerToString(i));
std::vector<bool> column_array;
OPT_GET("Subtitle/Grid/Column")->GetListBool(column_array);
for (int i=0;i<10;i++) showCol[i] = column_array.at(i);
SetColumnWidths();
// Update
@ -418,12 +422,12 @@ void BaseGrid::DrawImage(wxDC &dc) {
dc.SetFont(font);
// Clear background
dc.SetBackground(wxBrush(Options.AsColour(_T("Grid Background"))));
dc.SetBackground(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Background")->GetColour())));
dc.Clear();
// Draw labels
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(Options.AsColour(_T("Grid left column"))));
dc.SetBrush(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Left Column")->GetColour())));
dc.DrawRectangle(0,lineHeight,colWidth[0],h-lineHeight);
// Visible lines
@ -434,23 +438,23 @@ void BaseGrid::DrawImage(wxDC &dc) {
// Row colors
std::vector<wxBrush> rowColors;
std::vector<wxColor> foreColors;
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid Background")))); // 0 = Standard
foreColors.push_back(Options.AsColour(_T("Grid standard foreground")));
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid Header")))); // 1 = Header
foreColors.push_back(Options.AsColour(_T("Grid standard foreground")));
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid selection background")))); // 2 = Selected
foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid comment background")))); // 3 = Commented
foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid inframe background")))); // 4 = Video Highlighted
foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
rowColors.push_back(wxBrush(Options.AsColour(_T("Grid selected comment background")))); // 5 = Commented & selected
foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Background")->GetColour()))); // 0 = Standard
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Standard")->GetColour()));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Header")->GetColour()))); // 1 = Header
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Standard")->GetColour()));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColour()))); // 2 = Selected
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Selection")->GetColour()));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Comment")->GetColour()))); // 3 = Commented
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Selection")->GetColour()));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Inframe")->GetColour()))); // 4 = Video Highlighted
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Selection")->GetColour()));
rowColors.push_back(wxBrush(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Background/Selected Comment")->GetColour()))); // 5 = Commented & selected
foreColors.push_back(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Selection")->GetColour()));
// First grid row
bool drawGrid = true;
if (drawGrid) {
dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Lines")->GetColour())));
dc.DrawLine(0,0,w,0);
dc.SetPen(*wxTRANSPARENT_PEN);
}
@ -516,12 +520,12 @@ void BaseGrid::DrawImage(wxDC &dc) {
strings.Add(curDiag->GetMarginString(2));
// Set text
int mode = Options.AsInt(_T("Grid Hide Overrides"));
int mode = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt();
wxString value = _T("");
// Hidden overrides
if (mode == 1 || mode == 2) {
wxString replaceWith = Options.AsText(_T("Grid hide overrides char"));
wxString replaceWith = lagi_wxString(OPT_GET("Subtitle/Grid/Hide Overrides Char")->GetString());
int textlen = curDiag->Text.Length();
int depth = 0;
wxChar curChar;
@ -550,7 +554,7 @@ void BaseGrid::DrawImage(wxDC &dc) {
if (inSel && curDiag->Comment) curColor = 5;
else if (inSel) curColor = 2;
else if (curDiag->Comment) curColor = 3;
else if (Options.AsBool(_T("Highlight subs in frame")) && IsDisplayed(curDiag)) curColor = 4;
else if (OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame")->GetBool() && IsDisplayed(curDiag)) curColor = 4;
}
else {
@ -564,7 +568,7 @@ void BaseGrid::DrawImage(wxDC &dc) {
}
// Set text color
if (collides) dc.SetTextForeground(Options.AsColour(_T("Grid collision foreground")));
if (collides) dc.SetTextForeground(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Collision")->GetColour()));
else {
dc.SetTextForeground(foreColors[curColor]);
}
@ -595,7 +599,7 @@ void BaseGrid::DrawImage(wxDC &dc) {
// Draw grid
dc.DestroyClippingRegion();
if (drawGrid) {
dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Lines")->GetColour())));
dc.DrawLine(0,dy+lineHeight,w,dy+lineHeight);
dc.SetPen(*wxTRANSPARENT_PEN);
}
@ -604,7 +608,7 @@ void BaseGrid::DrawImage(wxDC &dc) {
// Draw grid columns
dx = 0;
if (drawGrid) {
dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Lines")->GetColour())));
for (int i=0;i<10;i++) {
dx += colWidth[i];
dc.DrawLine(dx,0,dx,maxH);
@ -614,7 +618,7 @@ void BaseGrid::DrawImage(wxDC &dc) {
}
// Draw currently active line border
dc.SetPen(wxPen(Options.AsColour(_T("Grid Active border"))));
dc.SetPen(wxPen(lagi_wxColour(OPT_GET("Colour/Subtitle Grid/Active Border")->GetColour())));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dy = (editBox->linen+1-yPos) * lineHeight;
dc.DrawRectangle(0,dy,w,lineHeight+1);
@ -677,7 +681,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
// Get focus
if (event.ButtonDown()) {
if (Options.AsBool(_T("Grid Allow Focus"))) {
if (OPT_GET("Subtitle/Grid/Focus Allow")->GetBool()) {
SetFocus();
}
}

14
aegisub/src/compat.cpp Normal file
View file

@ -0,0 +1,14 @@
#include "compat.h"
#include "main.h"
wxArrayString lagi_MRU_wxAS(const wxString &list) {
wxArrayString work;
const agi::MRUManager::MRUListMap *map_list = AegisubApp::Get()->mru->Get(STD_STR(list));
for (agi::MRUManager::MRUListMap::const_iterator i_lst = map_list->begin(); i_lst != map_list->end(); ++i_lst) {
work.Add(wxString(i_lst->second));
}
return work;
}

15
aegisub/src/compat.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef AGI_PRE
#include <string>
#include <wx/colour.h>
#include <wx/arrstr.h>
#include <wx/string.h>
#endif
#include <libaegisub/colour.h>
#define STD_STR(x) std::string(x.mb_str())
inline wxColour lagi_wxColour(const agi::Colour &colour) { return wxColour(colour); }
inline wxString lagi_wxString(const std::string &str) { return wxString(str); }
wxArrayString lagi_MRU_wxAS(const wxString &list);

View file

@ -50,9 +50,11 @@
#include "ass_attachment.h"
#include "ass_file.h"
#include "compat.h"
#include "dialog_attachments.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "utils.h"
@ -153,7 +155,7 @@ void DialogAttachments::OnAttachFont(wxCommandEvent &event) {
wxArrayString filenames;
wxArrayString paths;
{
wxFileDialog diag (this,_("Choose file to be attached"), Options.AsText(_T("Fonts Collector Destination")), _T(""), _T("Font Files (*.ttf)|*.ttf"), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
wxFileDialog diag (this,_("Choose file to be attached"), lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString()), _T(""), _T("Font Files (*.ttf)|*.ttf"), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
if (diag.ShowModal() == wxID_CANCEL) return;
diag.GetFilenames(filenames);
diag.GetPaths(paths);
@ -230,11 +232,11 @@ void DialogAttachments::OnExtract(wxCommandEvent &event) {
bool fullPath = false;
// Multiple or single?
if (listView->GetNextSelected(i) != -1) path = wxDirSelector(_("Select the path to save the files to:"),Options.AsText(_T("Fonts Collector Destination"))) + _T("/");
if (listView->GetNextSelected(i) != -1) path = wxDirSelector(_("Select the path to save the files to:"),lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString())) + _T("/");
else {
// Default path
wxString defPath = ((AssAttachment*) wxUIntToPtr(listView->GetItemData(i)))->GetFileName();
path = wxFileSelector(_("Select the path to save the file to:"),Options.AsText(_T("Fonts Collector Destination")),defPath);
path = wxFileSelector(_("Select the path to save the file to:"),lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString()),defPath);
fullPath = true;
}
if (path.IsEmpty()) return;

View file

@ -47,6 +47,7 @@
#endif
#include "auto4_base.h"
#include "compat.h"
#include "dialog_automation.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
@ -230,12 +231,12 @@ void DialogAutomation::OnAdd(wxCommandEvent &evt)
fnfilter = _T("All supported scripts|") + catchall + _T("|") + fnfilter;
}
wxString fname = wxFileSelector(_("Add Automation script"), Options.AsText(_T("Last open automation path")), wxEmptyString, wxEmptyString, fnfilter, wxFD_OPEN|wxFD_FILE_MUST_EXIST, this);
wxString fname = wxFileSelector(_("Add Automation script"), lagi_wxString(OPT_GET("Path/Last/Automation")->GetString()), wxEmptyString, wxEmptyString, fnfilter, wxFD_OPEN|wxFD_FILE_MUST_EXIST, this);
if (!fname.IsEmpty()) {
wxFileName fnpath(fname);
Options.SetText(_T("Last open automation path"), fnpath.GetPath());
OPT_SET("Path/Last/Automation")->SetString(STD_STR(fnpath.GetPath()));
// TODO: make sure each script is only loaded once. check in both local and global managers!!
// it doesn't break for macros, but will for export filters, and maybe for file formats,

View file

@ -56,9 +56,11 @@
#include "ass_style.h"
#include "colorspace.h"
#include "compat.h"
#include "dialog_colorpicker.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "utils.h"
@ -723,7 +725,7 @@ DialogColorPicker::DialogColorPicker(wxWindow *parent, wxColour initial_color)
wxSizer *recent_sizer = new wxBoxSizer(wxVERTICAL);
recent_sizer->Add(recent_box, 1, wxEXPAND);
if (Options.AsBool(_T("RGBAdjust Tool"))) recent_sizer->Add(new wxButton(this,BUTTON_RGBADJUST,_T("rgbadjust()")), 0, wxEXPAND);
if (OPT_GET("Tool/Colour Picker/RGBAdjust Tool")->GetBool()) recent_sizer->Add(new wxButton(this,BUTTON_RGBADJUST,_T("rgbadjust()")), 0, wxEXPAND);
wxSizer *picker_sizer = new wxBoxSizer(wxHORIZONTAL);
picker_sizer->AddStretchSpacer();
@ -764,11 +766,11 @@ DialogColorPicker::DialogColorPicker(wxWindow *parent, wxColour initial_color)
// Fill the controls
updating_controls = false;
int mode = Options.AsInt(_T("Color Picker Mode"));
int mode = OPT_GET("Tool/Colour Picker/Mode")->GetInt();
if (mode < 0 || mode > 4) mode = 3; // HSL default
colorspace_choice->SetSelection(mode);
SetColor(initial_color);
recent_box->LoadFromString(Options.AsText(_T("Color Picker Recent")));
recent_box->LoadFromString(lagi_wxString(OPT_GET("Tool/Colour Picker/Recent")->GetString()));
// The mouse event handler for the Dropper control must be manually assigned
// The EVT_MOUSE_EVENTS macro can't take a control id
@ -821,8 +823,7 @@ void DialogColorPicker::SetColor(wxColour new_color)
wxColour DialogColorPicker::GetColor()
{
recent_box->AddColor(cur_color);
Options.SetText(_T("Color Picker Recent"), recent_box->StoreToString());
Options.Save();
OPT_SET("Tool/Colour Picker/Recent")->SetString(STD_STR(recent_box->StoreToString()));
return cur_color;
}
@ -1326,7 +1327,7 @@ void DialogColorPicker::OnChangeMode(wxCommandEvent &evt)
{
if (!updating_controls)
spectrum_dirty = true;
Options.SetInt(_T("Color Picker Mode"), colorspace_choice->GetSelection());
OPT_SET("Tool/Colour Picker/Mode")->SetInt(colorspace_choice->GetSelection());
UpdateSpectrumDisplay();
}

View file

@ -44,6 +44,7 @@
#include "dialog_detached_video.h"
#include "frame_main.h"
#include "main.h"
#include "options.h"
#include "video_box.h"
#include "video_context.h"
@ -63,10 +64,10 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *par, const wxSize &initialDi
parent = par;
// Set up window
int x = Options.AsInt(_T("Detached video last x"));
int y = Options.AsInt(_T("Detached video last y"));
int x = OPT_GET("Video/Detached/Last/X")->GetInt();
int y = OPT_GET("Video/Detached/Last/Y")->GetInt();
if (x != -1 && y != -1) SetPosition(wxPoint(x,y));
if (Options.AsBool(_T("Detached video maximized"))) Maximize();
if (OPT_GET("Video/Detached/Maximized")->GetBool()) Maximize();
// Set obscure stuff
SetExtraStyle((GetExtraStyle() & ~wxWS_EX_BLOCK_EVENTS) | wxWS_EX_PROCESS_UI_UPDATES);
@ -127,10 +128,9 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *par, const wxSize &initialDi
// Update
parent->SetDisplayMode(0, -1);
GetPosition(&x, &y);
Options.SetInt(_T("Detached video last x"), x);
Options.SetInt(_T("Detached video last y"), y);
Options.SetBool(_T("Detached video"),true);
Options.Save();
OPT_SET("Video/Detached/Last/X")->SetInt(x);
OPT_SET("Video/Detached/Last/Y")->SetInt(y);
OPT_SET("Video/Detached/Enabled")->SetBool(true);
// Copy the main accelerator table to this dialog
wxAcceleratorTable *table = par->GetAcceleratorTable();
@ -139,8 +139,7 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *par, const wxSize &initialDi
/// @brief Destructor
DialogDetachedVideo::~DialogDetachedVideo() {
Options.SetBool(_T("Detached video maximized"),IsMaximized());
Options.Save();
OPT_SET("Video/Detached/Maximized")->SetBool(IsMaximized());
}
// Event table
@ -154,7 +153,7 @@ END_EVENT_TABLE()
/// @param event UNUSED
void DialogDetachedVideo::OnClose(wxCloseEvent &WXUNUSED(event)) {
FrameMain *par = parent;
Options.SetBool(_T("Detached video"),false);
OPT_SET("Video/Detached/Enabled")->SetBool(false);
Destroy();
par->detachedVideo = NULL;
par->SetDisplayMode(1,-1);
@ -164,8 +163,8 @@ void DialogDetachedVideo::OnClose(wxCloseEvent &WXUNUSED(event)) {
/// @param event
void DialogDetachedVideo::OnMove(wxMoveEvent &event) {
wxPoint pos = event.GetPosition();
Options.SetInt(_T("Detached video last x"),pos.x);
Options.SetInt(_T("Detached video last y"),pos.y);
OPT_SET("Video/Detached/Last/X")->SetInt(pos.x);
OPT_SET("Video/Detached/Last/Y")->SetInt(pos.y);
}
/// @brief Minimize event handler

View file

@ -44,10 +44,12 @@
#include <wx/statline.h>
#endif
#include "compat.h"
#include "dialog_dummy_video.h"
#include "help_button.h"
#include "main.h"
#include "options.h"
#include "utils.h"
/// DOCME
struct ResolutionShortcut {
@ -123,12 +125,12 @@ bool DialogDummyVideo::CreateDummyVideo(wxWindow *parent, wxString &out_filename
pattern = dlg.pattern->GetValue();
// Write to options
Options.SetFloat(_T("Video Dummy Last FPS"), fps);
Options.SetInt(_T("Video Dummy Last Width"), width);
Options.SetInt(_T("Video Dummy Last Height"), height);
Options.SetInt(_T("Video Dummy Last Length"), length);
Options.SetColour(_T("Video Dummy Last Colour"), colour);
Options.SetBool(_T("Video Dummy Pattern"), pattern);
OPT_SET("Video/Dummy/FPS")->SetDouble(fps);
OPT_SET("Video/Dummy/Last/Width")->SetInt(width);
OPT_SET("Video/Dummy/Last/Height")->SetInt(height);
OPT_SET("Video/Dummy/Last/Length")->SetInt(length);
OPT_SET("Colour/Video Dummy/Last Colour")->SetColour(STD_STR(colour.GetAsString(wxC2S_CSS_SYNTAX)));
OPT_SET("Video/Dummy/Pattern")->SetBool(pattern);
out_filename = DummyVideoProvider::MakeFilename(fps, length, width, height, colour, pattern);
return true;
@ -150,10 +152,10 @@ DialogDummyVideo::DialogDummyVideo(wxWindow *parent)
resolution_shortcuts = new wxComboBox(this, Dummy_Video_Resolution_Shortcut, _T(""), wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY);
width = new wxTextCtrl(this, -1);
height = new wxTextCtrl(this, -1);
colour = new ColourButton(this, -1, wxSize(30, 17), Options.AsColour(_T("Video Dummy Last Colour")));
colour = new ColourButton(this, -1, wxSize(30, 17), lagi_wxColour(OPT_GET("Colour/Video Dummy/Last Colour")->GetColour()));
pattern = new wxCheckBox(this, -1, _("Checkerboard pattern"));
//fps = new wxComboBox(this, Dummy_Video_FPS, Options.AsText(_T("Video Dummy Last FPS")), wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_DROPDOWN);
fps = new wxTextCtrl(this, Dummy_Video_FPS, Options.AsText(_T("Video Dummy Last FPS")));
fps = new wxTextCtrl(this, Dummy_Video_FPS, wxString::Format("%f", OPT_GET("Video/Dummy/FPS")->GetDouble()));
length = new wxSpinCtrl(this, Dummy_Video_Length);
length_display = new wxStaticText(this, -1, _T(""));
@ -195,24 +197,24 @@ DialogDummyVideo::DialogDummyVideo(wxWindow *parent)
// Initialise controls
int lastwidth, lastheight, lastres = 0;
lastwidth = Options.AsInt(_T("Video Dummy Last Width"));
lastheight = Options.AsInt(_T("Video Dummy Last Height"));
lastwidth = OPT_GET("Video/Dummy/Last/Width")->GetInt();
lastheight = OPT_GET("Video/Dummy/Last/Height")->GetInt();
for (ResolutionShortcut *res = resolutions; res->name; ++res) {
resolution_shortcuts->Append(res->name);
if (res->width == lastwidth && res->height == lastheight)
resolution_shortcuts->SetSelection(lastres);
lastres++;
}
pattern->SetValue(Options.AsBool(_T("Video Dummy Pattern")));
pattern->SetValue(OPT_GET("Video/Dummy/Pattern")->GetBool());
/*fps->Append(_T("23.976"));
fps->Append(_T("29.97"));
fps->Append(_T("24"));
fps->Append(_T("25"));
fps->Append(_T("30"));*/
width->ChangeValue(Options.AsText(_T("Video Dummy Last Width")));
height->ChangeValue(Options.AsText(_T("Video Dummy Last Height")));
width->ChangeValue(AegiIntegerToString(OPT_GET("Video/Dummy/Last/Width")->GetInt()));
height->ChangeValue(AegiIntegerToString(OPT_GET("Video/Dummy/Last/Height")->GetInt()));
length->SetRange(0, 0x10000000);
length->SetValue(Options.AsInt(_T("Video Dummy Last Length")));
length->SetValue(OPT_GET("Video/Dummy/Last/Length")->GetInt());
UpdateLengthDisplay();
// Layout

View file

@ -51,11 +51,13 @@
#include "ass_file.h"
#include "ass_override.h"
#include "ass_style.h"
#include "compat.h"
#include "dialog_fonts_collector.h"
#include "font_file_lister.h"
#include "frame_main.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "scintilla_text_ctrl.h"
#include "subs_grid.h"
@ -96,7 +98,7 @@ DialogFontsCollector::DialogFontsCollector(wxWindow *parent)
main = (FrameMain*) parent;
// Destination box
wxString dest = Options.AsText(_T("Fonts Collector Destination"));
wxString dest = lagi_wxString(OPT_GET("Path/Fonts Collector Destination")->GetString());
if (dest == _T("?script")) {
wxFileName filename(AssFile::top->filename);
dest = filename.GetPath();
@ -122,7 +124,7 @@ DialogFontsCollector::DialogFontsCollector(wxWindow *parent)
choices.Add(_("DEBUG: Verify all fonts in system"));
#endif
CollectAction = new wxRadioBox(this,RADIO_BOX,_T("Action"),wxDefaultPosition,wxDefaultSize,choices,1);
size_t lastAction = Options.AsInt(_T("Fonts Collector Action"));
size_t lastAction = OPT_GET("Tool/Fonts Collector/Action")->GetInt();
if (lastAction >= choices.GetCount()) lastAction = 0;
CollectAction->SetSelection(lastAction);
@ -241,10 +243,9 @@ void DialogFontsCollector::OnStart(wxCommandEvent &event) {
if (filename.GetPath() == dest) {
dest = _T("?script");
}
Options.SetText(_T("Fonts Collector Destination"),dest);
OPT_SET("Path/Fonts Collector Destination")->SetString(STD_STR(dest));
}
Options.SetInt(_T("Fonts Collector Action"),action);
Options.Save();
OPT_SET("Tool/Fonts Collector/Action")->SetInt(action);
// Set buttons
StartButton->Enable(false);

View file

@ -54,6 +54,7 @@
#include "dialog_kara_timing_copy.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "subs_grid.h"
#include "utils.h"
#include "validators.h"
@ -852,7 +853,7 @@ DialogKanjiTimer::DialogKanjiTimer(wxWindow *parent, SubtitlesGrid *_grid)
//Checkbox
Interpolate = new wxCheckBox(this,-1,_("Attempt to interpolate kanji."),wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT);
Interpolate->SetValue(Options.AsBool(_T("kanji timer interpolation")));
Interpolate->SetValue(OPT_GET("Tool/Kanji Timer/Interpolation")->GetBool());
SourceStyle=new wxComboBox(this,-1,_T(""),wxDefaultPosition,wxSize(160,-1),
subs->GetStyles(),wxCB_READONLY,wxDefaultValidator,_("Source Style"));
@ -934,8 +935,7 @@ END_EVENT_TABLE()
/// @param event
///
void DialogKanjiTimer::OnClose(wxCommandEvent &event) {
Options.SetBool(_T("kanji timer interpolation"),Interpolate->IsChecked());
Options.Save();
OPT_SET("Tool/Kanji Timer/Interpolation")->SetBool(Interpolate->IsChecked());
bool modified = !LinesToChange.empty();
while(LinesToChange.empty()==false) {

File diff suppressed because it is too large Load diff

View file

@ -1,186 +0,0 @@
// Copyright (c) 2006, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
//
// $Id$
/// @file dialog_options.h
/// @see dialog_options.cpp
/// @ingroup configuration_ui
///
////////////
// Includes
#ifndef AGI_PRE
#include <map>
#include <vector>
#include <wx/dialog.h>
#include <wx/listctrl.h>
#endif
#include "hotkeys.h"
#include "options.h"
//////////////
// Prototypes
class FrameMain;
class DialogInputHotkey;
#if wxUSE_TREEBOOK
class wxTreebook;
#else
#include <wx/choicebk.h>
/// DOCME
typedef wxChoicebook wxTreebook;
#endif
/// DOCME
/// @class OptionsBind
/// @brief DOCME
///
/// DOCME
class OptionsBind {
public:
/// DOCME
wxControl *ctrl;
/// DOCME
wxString option;
/// DOCME
int param;
};
/// DOCME
enum TextType {
/// DOCME
TEXT_TYPE_PLAIN,
/// DOCME
TEXT_TYPE_NUMBER,
/// DOCME
TEXT_TYPE_FILE,
/// DOCME
TEXT_TYPE_FOLDER,
/// DOCME
TEXT_TYPE_FONT
};
/// DOCME
/// @class DialogOptions
/// @brief DOCME
///
/// DOCME
class DialogOptions: public wxDialog {
private:
/// DOCME
bool needsRestart;
/// DOCME
wxTreebook *book;
/// DOCME
std::vector<OptionsBind> binds;
/// DOCME
std::map<wxString,HotkeyType> origKeys;
/// DOCME
wxListView *Shortcuts;
/// DOCME
bool hotkeysModified;
void Bind(wxControl *ctrl,wxString option,int param=0);
void WriteToOptions(bool justApply=false);
void ReadFromOptions();
void AddTextControl(wxWindow *parent,wxSizer *sizer,wxString label,wxString option,TextType type=TEXT_TYPE_PLAIN);
void AddComboControl(wxWindow *parent,wxSizer *sizer,wxString label,wxString option,wxArrayString choices,bool readOnly=true,int bindParam=0);
void AddCheckBox(wxWindow *parent,wxSizer *sizer,wxString label,wxString option);
void OnOK(wxCommandEvent &event);
void OnCancel(wxCommandEvent &event);
void OnApply(wxCommandEvent &event);
void OnDefaults(wxCommandEvent &event);
void OnEditHotkey(wxCommandEvent &event);
void OnClearHotkey(wxCommandEvent &event);
void OnDefaultHotkey(wxCommandEvent &event);
void OnDefaultAllHotkey(wxCommandEvent &event);
public:
DialogOptions(wxWindow *parent);
~DialogOptions();
DECLARE_EVENT_TABLE()
};
/// DOCME
/// @class DialogInputHotkey
/// @brief DOCME
///
/// DOCME
class DialogInputHotkey : public wxDialog {
/// DOCME
HotkeyType *key;
/// DOCME
wxListView *shortcuts;
void OnKeyDown(wxKeyEvent &event);
public:
DialogInputHotkey(wxWindow *parent, HotkeyType *key, wxString name, wxListView *Shortcuts);
DECLARE_EVENT_TABLE()
};

View file

@ -48,6 +48,7 @@
#include "dialog_paste_over.h"
#include "help_button.h"
#include "main.h"
#include "options.h"
@ -87,7 +88,10 @@ DialogPasteOver::DialogPasteOver (wxWindow *parent)
ListSizer->Add(ListBox,0,wxEXPAND|wxTOP,5);
// Load checked items
for (unsigned int i=0;i<choices.Count();i++) ListBox->Check(i,Options.AsBool(wxString::Format(_T("Paste Over #%i"),i)));
/// @todo This assumes a static set of fields.
std::vector<bool> choice_array;
OPT_GET("Tool/Paste Lines Over/Fields")->GetListBool(choice_array);
for (unsigned int i=0;i<choices.Count();i++) ListBox->Check(i,choice_array.at(i));
// Top buttons
wxSizer *TopButtonSizer = new wxBoxSizer(wxHORIZONTAL);
@ -138,15 +142,13 @@ END_EVENT_TABLE()
/// @param event
///
void DialogPasteOver::OnOK(wxCommandEvent &event) {
// Set options
options.SetCount(10);
for (int i=0;i<10;i++) {
options[i] = ListBox->IsChecked(i) ? 1 : 0;
Options.SetBool(wxString::Format(_T("Paste Over #%i"),i),options[i]==1);
}
Options.Save();
// End
std::vector<bool> map;
for (int i=0;i<10;i++) {
map[i] = ListBox->IsChecked(i);
}
OPT_SET("Tool/Paste Lines Over/Fields")->SetListBool(map);
EndModal(1);
}

View file

@ -44,6 +44,7 @@
#include <wx/string.h>
#endif
#include "compat.h"
#include "ass_dialogue.h"
#include "ass_file.h"
#include "dialog_search_replace.h"
@ -68,14 +69,14 @@ DialogSearchReplace::DialogSearchReplace (wxWindow *parent,bool _hasReplace,wxSt
// Find sizer
wxSizer *FindSizer = new wxFlexGridSizer(2,2,5,15);
wxArrayString FindHistory = Options.GetRecentList(_T("Recent find"));
wxArrayString FindHistory = lagi_MRU_wxAS("Find");
FindEdit = new wxComboBox(this,-1,_T(""),wxDefaultPosition,wxSize(300,-1),FindHistory,wxCB_DROPDOWN);
//if (FindHistory.Count()) FindEdit->SetStringSelection(FindHistory[0]);
FindEdit->SetSelection(0);
FindSizer->Add(new wxStaticText(this,-1,_("Find what:")),0,wxRIGHT | wxALIGN_CENTER_VERTICAL,0);
FindSizer->Add(FindEdit,0,wxRIGHT,0);
if (hasReplace) {
wxArrayString ReplaceHistory = Options.GetRecentList(_T("Recent replace"));
wxArrayString ReplaceHistory = lagi_MRU_wxAS("Replace");
ReplaceEdit = new wxComboBox(this,-1,_T(""),wxDefaultPosition,wxSize(300,-1),ReplaceHistory,wxCB_DROPDOWN);
FindSizer->Add(new wxStaticText(this,-1,_("Replace with:")),0,wxRIGHT | wxALIGN_CENTER_VERTICAL,0);
FindSizer->Add(ReplaceEdit,0,wxRIGHT,0);
@ -87,10 +88,10 @@ DialogSearchReplace::DialogSearchReplace (wxWindow *parent,bool _hasReplace,wxSt
CheckMatchCase = new wxCheckBox(this,CHECK_MATCH_CASE,_("Match case"));
CheckRegExp = new wxCheckBox(this,CHECK_MATCH_CASE,_("Use regular expressions"));
CheckUpdateVideo = new wxCheckBox(this,CHECK_UPDATE_VIDEO,_("Update Video (slow)"));
CheckMatchCase->SetValue(Options.AsBool(_T("Find Match Case")));
CheckRegExp->SetValue(Options.AsBool(_T("Find RegExp")));
CheckMatchCase->SetValue(OPT_GET("Tool/Search Replace/Match Case")->GetBool());
CheckRegExp->SetValue(OPT_GET("Tool/Search Replace/RegExp")->GetBool());
//CheckRegExp->Enable(false);
CheckUpdateVideo->SetValue(Options.AsBool(_T("Find Update Video")));
CheckUpdateVideo->SetValue(OPT_GET("Tool/Search Replace/Video Update")->GetBool());
// CheckUpdateVideo->Enable(Search.grid->video->loaded);
OptionsSizer->Add(CheckMatchCase,0,wxBOTTOM,5);
OptionsSizer->Add(CheckRegExp,0,wxBOTTOM,5);
@ -110,8 +111,8 @@ DialogSearchReplace::DialogSearchReplace (wxWindow *parent,bool _hasReplace,wxSt
wxSizer *LimitSizer = new wxBoxSizer(wxHORIZONTAL);
LimitSizer->Add(Field,1,wxEXPAND | wxRIGHT,5);
LimitSizer->Add(Affect,0,wxEXPAND | wxRIGHT,0);
Field->SetSelection(Options.AsInt(_T("Find Field")));
Affect->SetSelection(Options.AsInt(_T("Find Affect")));
Field->SetSelection(OPT_GET("Tool/Search Replace/Field")->GetInt());
Affect->SetSelection(OPT_GET("Tool/Search Replace/Affect")->GetInt());
// Left sizer
wxSizer *LeftSizer = new wxBoxSizer(wxVERTICAL);
@ -160,12 +161,11 @@ void DialogSearchReplace::UpdateSettings() {
Search.isReg = CheckRegExp->IsChecked() && CheckRegExp->IsEnabled();
Search.matchCase = CheckMatchCase->IsChecked();
Search.updateVideo = CheckUpdateVideo->IsChecked() && CheckUpdateVideo->IsEnabled();
Options.SetBool(_T("Find Match Case"),CheckMatchCase->IsChecked());
Options.SetBool(_T("Find RegExp"),CheckRegExp->IsChecked());
Options.SetBool(_T("Find Update Video"),CheckUpdateVideo->IsChecked());
Options.SetInt(_T("Find Field"),Field->GetSelection());
Options.SetInt(_T("Find Affect"),Affect->GetSelection());
Options.Save();
OPT_SET("Tool/Search Replace/Match Case")->SetBool(CheckMatchCase->IsChecked());
OPT_SET("Tool/Search Replace/RegExp")->SetBool(CheckRegExp->IsChecked());
OPT_SET("Tool/Search Replace/Video Update")->SetBool(CheckUpdateVideo->IsChecked());
OPT_SET("Tool/Search Replace/Field")->SetInt(Field->GetSelection());
OPT_SET("Tool/Search Replace/Affect")->SetInt(Affect->GetSelection());
}
@ -234,7 +234,7 @@ void DialogSearchReplace::FindReplace(int mode) {
if (hasReplace) {
wxString ReplaceWith = ReplaceEdit->GetValue();
Search.ReplaceWith = ReplaceWith;
Options.AddToRecentList(ReplaceWith,_T("Recent replace"));
AegisubApp::Get()->mru->Add("Replace", STD_STR(ReplaceWith));
}
}
@ -244,11 +244,11 @@ void DialogSearchReplace::FindReplace(int mode) {
Search.ReplaceWith = ReplaceWith;
if (mode == 1) Search.ReplaceNext();
else Search.ReplaceAll();
Options.AddToRecentList(ReplaceWith,_T("Recent replace"));
AegisubApp::Get()->mru->Add("Replace", STD_STR(ReplaceWith));
}
// Add to history
Options.AddToRecentList(LookFor,_T("Recent find"));
AegisubApp::Get()->mru->Add("Find", STD_STR(LookFor));
UpdateDropDowns();
}
@ -287,7 +287,7 @@ void DialogSearchReplace::UpdateDropDowns() {
// Find
FindEdit->Freeze();
FindEdit->Clear();
FindEdit->Append(Options.GetRecentList(_T("Recent find")));
FindEdit->Append(lagi_MRU_wxAS("Find"));
FindEdit->SetSelection(0);
FindEdit->Thaw();
@ -295,7 +295,7 @@ void DialogSearchReplace::UpdateDropDowns() {
if (hasReplace) {
ReplaceEdit->Freeze();
ReplaceEdit->Clear();
ReplaceEdit->Append(Options.GetRecentList(_T("Recent replace")));
ReplaceEdit->Append(lagi_MRU_wxAS("Replace"));
ReplaceEdit->SetSelection(0);
ReplaceEdit->Thaw();
}

View file

@ -45,8 +45,10 @@
#endif
#include "ass_dialogue.h"
#include "compat.h"
#include "dialog_selection.h"
#include "help_button.h"
#include "main.h"
#include "options.h"
#include "subs_grid.h"
#include "subs_edit_box.h"
@ -70,7 +72,7 @@ wxDialog (parent,-1,_("Select"),wxDefaultPosition,wxDefaultSize,wxCAPTION)
// Matches box
Matches = new wxRadioButton(this,-1,_("Matches"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP);
DoesntMatch = new wxRadioButton(this,-1,_("Doesn't Match"),wxDefaultPosition,wxDefaultSize,0);
Match = new wxTextCtrl(this,-1,Options.AsText(_T("Select Text")),wxDefaultPosition,wxSize(200,-1));
Match = new wxTextCtrl(this,-1,lagi_wxString(OPT_GET("Tool/Select Lines/Text")->GetString()),wxDefaultPosition,wxSize(200,-1));
MatchCase = new wxCheckBox(this,-1,_("Match case"));
Exact = new wxRadioButton(this,-1,_("Exact match"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP);
Contains = new wxRadioButton(this,-1,_("Contains"));
@ -130,13 +132,13 @@ wxDialog (parent,-1,_("Select"),wxDefaultPosition,wxDefaultSize,wxCAPTION)
CenterOnParent();
// Load settings
Field->SetSelection(Options.AsInt(_T("Select Field")));
Action->SetSelection(Options.AsInt(_T("Select Action")));
MatchCase->SetValue(Options.AsBool(_T("Select Match case")));
MatchDialogues->SetValue(Options.AsBool(_T("Select Match dialogues")));
MatchComments->SetValue(Options.AsBool(_T("Select Match comments")));
int condition = Options.AsInt(_T("Select Condition"));
int mode = Options.AsInt(_T("Select Mode"));
Field->SetSelection(OPT_GET("Tool/Select/Field")->GetInt());
Action->SetSelection(OPT_GET("Tool/Select/Action")->GetInt());
MatchCase->SetValue(OPT_GET("Tool/Select Lines/Match/Case")->GetBool());
MatchDialogues->SetValue(OPT_GET("Tool/Select Lines/Match/Dialogue")->GetBool());
MatchComments->SetValue(OPT_GET("Tool/Select Lines/Match/Comment")->GetBool());
int condition = OPT_GET("Tool/Select/Condition")->GetInt();
int mode = OPT_GET("Tool/Select/Mode")->GetInt();
if (condition == 1) DoesntMatch->SetValue(true);
if (mode == 1) Contains->SetValue(true);
else if (mode == 2) RegExp->SetValue(true);
@ -303,14 +305,14 @@ void DialogSelection::SaveSettings() {
else condition = 1;
// Store
Options.SetText(_T("Select Text"),Match->GetValue());
Options.SetInt(_T("Select Condition"),condition);
Options.SetInt(_T("Select Field"),field);
Options.SetInt(_T("Select Action"),action);
Options.SetInt(_T("Select Mode"),mode);
Options.SetBool(_T("Select Match case"),MatchCase->IsChecked());
Options.SetBool(_T("Select Match dialogues"),MatchDialogues->IsChecked());
Options.SetBool(_T("Select Match comments"),MatchComments->IsChecked());
OPT_SET("Tool/Select Lines/Text")->SetString(STD_STR(Match->GetValue()));
OPT_SET("Tool/Select/Condition")->SetInt(condition);
OPT_SET("Tool/Select/Field")->SetInt(field);
OPT_SET("Tool/Select/Action")->SetInt(action);
OPT_SET("Tool/Select/Mode")->SetInt(mode);
OPT_SET("Tool/Select Lines/Match/Case")->SetBool(MatchCase->IsChecked());
OPT_SET("Tool/Select Lines/Match/Dialogue")->SetBool(MatchDialogues->IsChecked());
OPT_SET("Tool/Select Lines/Match/Comment")->SetBool(MatchComments->IsChecked());
}

View file

@ -55,6 +55,7 @@
#include "dialog_shift_times.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "subs_edit_box.h"
@ -154,20 +155,20 @@ DialogShiftTimes::DialogShiftTimes (wxWindow *parent,SubtitlesGrid *_grid)
CenterOnParent();
// Load values from options
if (!Options.AsBool(_T("Shift Times ByTime"))) {
if (!OPT_GET("Tools/Shift Times/ByTime")->GetBool()) {
if (RadioFrames->IsEnabled()) {
RadioFrames->SetValue(true);
ShiftFrame->Enable(true);
ShiftTime->Enable(false);
ShiftFrame->SetValue(Options.AsText(_T("Shift Times Length")));
ShiftFrame->SetValue(AegiIntegerToString(OPT_GET("Tool/Shift Times/Length")->GetInt()));
}
}
else {
ShiftTime->SetTime(Options.AsInt(_T("Shift Times Length")));
ShiftTime->SetTime(OPT_GET("Tool/Shift Times/Length")->GetInt());
}
TimesChoice->SetSelection(Options.AsInt(_T("Shift Times Type")));
SelChoice->SetSelection(Options.AsInt(_T("Shift Times Affect")));
if (Options.AsBool(_T("Shift Times Direction"))) DirectionBackward->SetValue(true);
TimesChoice->SetSelection(OPT_GET("Tool/Shift Times/Type")->GetInt());
SelChoice->SetSelection(OPT_GET("Tool/Shift Times/Affect")->GetInt());
if (OPT_GET("Tools/Shift Times/Direction")->GetBool()) DirectionBackward->SetValue(true);
// Has selection?
wxArrayInt sel = grid->GetSelection();
@ -304,12 +305,11 @@ void DialogShiftTimes::OnOK(wxCommandEvent &event) {
}
// Store modifications
Options.SetBool(_T("Shift Times ByTime"),byTime);
Options.SetInt(_T("Shift Times Type"),type);
Options.SetInt(_T("Shift Times Length"),len);
Options.SetInt(_T("Shift Times Affect"),affect);
Options.SetBool(_T("Shift Times Direction"),backward);
Options.Save();
OPT_SET("Tools/Shift Times/ByTime")->SetBool(byTime);
OPT_SET("Tool/Shift Times/Type")->SetInt(type);
OPT_SET("Tool/Shift Times/Length")->SetInt(len);
OPT_SET("Tool/Shift Times/Affect")->SetInt(affect);
OPT_SET("Tools/Shift Times/Direction")->SetBool(backward);
// End dialog
grid->ass->FlagAsModified(_("shifting"));

View file

@ -44,10 +44,12 @@
#include "ass_dialogue.h"
#include "ass_file.h"
#include "compat.h"
#include "dialog_spellchecker.h"
#include "frame_main.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "spellchecker_manager.h"
#include "subs_edit_box.h"
@ -114,7 +116,7 @@ DialogSpellChecker::DialogSpellChecker(wxFrame *parent)
}
// Get current language
wxString curLang = Options.AsText(_T("Spell checker language"));
wxString curLang = lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString());
int curLangPos = langCodes.Index(curLang);
if (curLangPos == wxNOT_FOUND) {
curLangPos = langCodes.Index(_T("en"));
@ -401,8 +403,7 @@ void DialogSpellChecker::OnChangeLanguage(wxCommandEvent &event) {
// Change language code
wxString code = langCodes[language->GetSelection()];
spellchecker->SetLanguage(code);
Options.SetText(_T("Spell checker language"),code);
Options.Save();
OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(code));
// Go back to first match
GetFirstMatch();

View file

@ -50,10 +50,12 @@
#include "ass_override.h"
#include "ass_style.h"
#include "ass_style_storage.h"
#include "compat.h"
#include "dialog_colorpicker.h"
#include "dialog_style_editor.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "subs_grid.h"
#include "subs_preview.h"
@ -362,9 +364,9 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *_style, Subtit
SubsPreview = NULL;
PreviewText = NULL;
if (SubtitlesProviderFactoryManager::ProviderAvailable()) {
PreviewText = new wxTextCtrl(this,TEXT_PREVIEW,Options.AsText(_T("Style editor preview text")));
previewButton = new ColourButton(this,BUTTON_PREVIEW_COLOR,wxSize(45,16),Options.AsColour(_T("Style editor preview background")));
SubsPreview = new SubtitlesPreview(this,-1,wxDefaultPosition,wxSize(100,60),wxSUNKEN_BORDER,Options.AsColour(_T("Style editor preview background")));
PreviewText = new wxTextCtrl(this,TEXT_PREVIEW,lagi_wxString(OPT_GET("Tool/Style Editor/Preview Text")->GetString()));
previewButton = new ColourButton(this,BUTTON_PREVIEW_COLOR,wxSize(45,16),lagi_wxColour(OPT_GET("Colour/Style Editor/Background/Preview")->GetColour()));
SubsPreview = new SubtitlesPreview(this,-1,wxDefaultPosition,wxSize(100,60),wxSUNKEN_BORDER,lagi_wxColour(OPT_GET("Colour/Style Editor/Background/Preview")->GetColour()));
SubsPreview->SetToolTip(_("Preview of current style."));
SubsPreview->SetStyle(style);
@ -588,8 +590,7 @@ void DialogStyleEditor::Apply (bool apply,bool close) {
// Exit
if (close) {
EndModal(1);
if (PreviewText) Options.SetText(_T("Style editor preview text"),PreviewText->GetValue());
Options.Save();
if (PreviewText) OPT_SET("Tool/Style Editor/Preview Text")->SetString(STD_STR(PreviewText->GetValue()));
}
// Update preview
@ -600,8 +601,7 @@ void DialogStyleEditor::Apply (bool apply,bool close) {
else {
if (close) {
EndModal(0);
if (PreviewText) Options.SetText(_T("Style editor preview text"),PreviewText->GetValue());
Options.Save();
if (PreviewText) OPT_SET("Tool/Style Editor/Preview Text")->SetString(STD_STR(PreviewText->GetValue()));
}
}
}
@ -722,8 +722,7 @@ void DialogStyleEditor::OnPreviewTextChange (wxCommandEvent &event) {
///
void DialogStyleEditor::OnPreviewColourChange (wxCommandEvent &event) {
if (SubsPreview) SubsPreview->SetColour(previewButton->GetColour());
Options.SetColour(_T("Style editor preview background"),previewButton->GetColour());
Options.Save();
OPT_SET("Colour/Style Editor/Background/Preview")->SetColour(STD_STR(previewButton->GetColour().GetAsString(wxC2S_CSS_SYNTAX)));
}
/// @brief Command event to update preview

View file

@ -47,10 +47,12 @@
#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_style.h"
#include "compat.h"
#include "dialog_style_editor.h"
#include "dialog_style_manager.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "standard_paths.h"
#include "subs_grid.h"
@ -829,14 +831,13 @@ void DialogStyleManager::OnCurrentDelete (wxCommandEvent &) {
/// @brief Import styles from another script
void DialogStyleManager::OnCurrentImport(wxCommandEvent &) {
// Get file name
wxString path = Options.AsText(_T("Last open subtitles path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.IsEmpty()) {
// Save path
wxFileName filepath(filename);
Options.SetText(_T("Last open subtitles path"), filepath.GetPath());
Options.Save();
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
try {
// Load file

View file

@ -44,7 +44,9 @@
#include <wx/stattext.h>
#endif
#include "compat.h"
#include "dialog_text_import.h"
#include "main.h"
#include "options.h"
@ -56,8 +58,8 @@ DialogTextImport::DialogTextImport()
// Main controls
wxFlexGridSizer *fg = new wxFlexGridSizer(2, 5, 5);
wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
edit_separator = new wxTextCtrl(this, EDIT_ACTOR_SEPARATOR, Options.AsText(_T("text actor separator")));
edit_comment = new wxTextCtrl(this, EDIT_COMMENT_STARTER, Options.AsText(_T("text comment starter")));
edit_separator = new wxTextCtrl(this, EDIT_ACTOR_SEPARATOR, lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString()));
edit_comment = new wxTextCtrl(this, EDIT_COMMENT_STARTER, lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString()));
// Dialog layout
fg->Add(new wxStaticText(this, -1, _("Actor separator:")), 0, wxALIGN_CENTRE_VERTICAL);
@ -85,9 +87,8 @@ DialogTextImport::~DialogTextImport()
void DialogTextImport::OnOK(wxCommandEvent &event)
{
// Set options
Options.SetText(_T("text actor separator"), edit_separator->GetValue());
Options.SetText(_T("text comment starter"), edit_comment->GetValue());
Options.Save();
OPT_SET("Tool/Import/Text/Actor Separator")->SetString(STD_STR(edit_separator->GetValue()));
OPT_SET("Tool/Import/Text/Comment Starter")->SetString(STD_STR(edit_comment->GetValue()));
EndModal(wxID_OK);
}

View file

@ -44,6 +44,7 @@
#include "dialog_timing_processor.h"
#include "help_button.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "subs_grid.h"
#include "utils.h"
@ -66,13 +67,14 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr
// Set variables
grid = _grid;
leadInTime = Options.AsText(_T("Audio lead in"));
leadOutTime = Options.AsText(_T("Audio lead out"));
thresStartBefore = Options.AsText(_T("Timing processor key start before thres"));
thresStartAfter = Options.AsText(_T("Timing processor key start after thres"));
thresEndBefore = Options.AsText(_T("Timing processor key end before thres"));
thresEndAfter = Options.AsText(_T("Timing processor key end after thres"));
adjsThresTime = Options.AsText(_T("Timing processor adjacent thres"));
leadInTime = AegiIntegerToString(OPT_GET("Audio/Lead/IN")->GetInt());
leadOutTime = AegiIntegerToString(OPT_GET("Audio/Lead/OUT")->GetInt());
thresStartBefore = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key Start Before")->GetInt());
thresStartAfter = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key Start After")->GetInt());
thresEndBefore = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key End Before")->GetInt());
thresEndAfter = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Key End After")->GetInt());
adjsThresTime = AegiIntegerToString(OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt());
// Styles box
wxSizer *LeftSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Apply to styles"));
@ -87,19 +89,19 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr
// Options box
wxSizer *optionsSizer = new wxStaticBoxSizer(wxHORIZONTAL,this,_("Options"));
onlySelection = new wxCheckBox(this,-1,_("Affect selection only"));
onlySelection->SetValue(Options.AsBool(_T("Timing processor Only Selection")));
onlySelection->SetValue(OPT_GET("Tool/Timing Post Processor/Only Selection")->GetBool());
optionsSizer->Add(onlySelection,1,wxALL,0);
// Lead-in/out box
wxSizer *LeadSizer = new wxStaticBoxSizer(wxHORIZONTAL,this,_("Lead-in/Lead-out"));
hasLeadIn = new wxCheckBox(this,CHECK_ENABLE_LEADIN,_("Add lead in:"));
hasLeadIn->SetToolTip(_("Enable adding of lead-ins to lines."));
hasLeadIn->SetValue(Options.AsBool(_T("Timing processor Enable lead-in")));
hasLeadIn->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Lead/IN")->GetBool());
leadIn = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(&leadInTime));
leadIn->SetToolTip(_("Lead in to be added, in milliseconds."));
hasLeadOut = new wxCheckBox(this,CHECK_ENABLE_LEADOUT,_("Add lead out:"));
hasLeadOut->SetToolTip(_("Enable adding of lead-outs to lines."));
hasLeadOut->SetValue(Options.AsBool(_T("Timing processor Enable lead-out")));
hasLeadOut->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Lead/OUT")->GetBool());
leadOut = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(&leadOutTime));
leadOut->SetToolTip(_("Lead out to be added, in milliseconds."));
LeadSizer->Add(hasLeadIn,0,wxRIGHT|wxEXPAND,5);
@ -112,11 +114,11 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr
wxSizer *AdjacentSizer = new wxStaticBoxSizer(wxHORIZONTAL,this,_("Make adjacent subtitles continuous"));
adjsEnable = new wxCheckBox(this,CHECK_ENABLE_ADJASCENT,_("Enable"));
adjsEnable->SetToolTip(_("Enable snapping of subtitles together if they are within a certain distance of each other."));
adjsEnable->SetValue(Options.AsBool(_T("Timing processor Enable adjacent")));
adjsEnable->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Adjacent")->GetBool());
wxStaticText *adjsThresText = new wxStaticText(this,-1,_("Threshold:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
adjacentThres = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&adjsThresTime));
adjacentThres->SetToolTip(_("Maximum difference between start and end time for two subtitles to be made continuous, in milliseconds."));
adjacentBias = new wxSlider(this,-1,MID(0,int(Options.AsFloat(_T("Timing processor adjacent bias"))*100),100),0,100,wxDefaultPosition,wxSize(-1,20));
adjacentBias = new wxSlider(this,-1,MID(0,int(OPT_GET("Tool/Timing Post Processor/Adjacent Bias")->GetDouble()*100),100),0,100,wxDefaultPosition,wxSize(-1,20));
adjacentBias->SetToolTip(_("Sets how to set the adjoining of lines. If set totally to left, it will extend start time of the second line; if totally to right, it will extend the end time of the first line."));
AdjacentSizer->Add(adjsEnable,0,wxRIGHT|wxEXPAND,10);
AdjacentSizer->Add(adjsThresText,0,wxRIGHT|wxALIGN_CENTER,5);
@ -130,7 +132,7 @@ DialogTimingProcessor::DialogTimingProcessor(wxWindow *parent,SubtitlesGrid *_gr
wxSizer *KeyframesFlexSizer = new wxFlexGridSizer(2,5,5,0);
keysEnable = new wxCheckBox(this,CHECK_ENABLE_KEYFRAME,_("Enable"));
keysEnable->SetToolTip(_("Enable snapping of subtitles to nearest keyframe, if distance is within threshold."));
keysEnable->SetValue(Options.AsBool(_T("Timing processor Enable keyframe")));
keysEnable->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Keyframe")->GetBool());
wxStaticText *textStartBefore = new wxStaticText(this,-1,_("Starts before thres.:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
keysStartBefore = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&thresStartBefore));
keysStartBefore->SetToolTip(_("Threshold for 'before start' distance, that is, how many frames a subtitle must start before a keyframe to snap to it."));
@ -293,26 +295,25 @@ void DialogTimingProcessor::OnApply(wxCommandEvent &event) {
// Save settings
long temp = 0;
leadIn->GetValue().ToLong(&temp);
Options.SetInt(_T("Audio lead in"),temp);
OPT_SET("Audio/Lead/IN")->SetInt(temp);
leadOut->GetValue().ToLong(&temp);
Options.SetInt(_T("Audio lead out"),temp);
OPT_SET("Audio/Lead/OUT")->SetInt(temp);
keysStartBefore->GetValue().ToLong(&temp);
Options.SetInt(_T("Timing processor key start before thres"),temp);
OPT_SET("Tool/Timing Post Processor/Threshold/Key Start Before")->SetInt(temp);
keysStartAfter->GetValue().ToLong(&temp);
Options.SetInt(_T("Timing processor key start after thres"),temp);
OPT_SET("Tool/Timing Post Processor/Threshold/Key Start After")->SetInt(temp);
keysEndBefore->GetValue().ToLong(&temp);
Options.SetInt(_T("Timing processor key end before thres"),temp);
OPT_SET("Tool/Timing Post Processor/Threshold/Key End Before")->SetInt(temp);
keysEndAfter->GetValue().ToLong(&temp);
Options.SetInt(_T("Timing processor key end after thres"),temp);
OPT_SET("Tool/Timing Post Processor/Threshold/Key End After")->SetInt(temp);
adjacentThres->GetValue().ToLong(&temp);
Options.SetInt(_T("Timing processor adjacent thres"),temp);
Options.SetFloat(_T("Timing processor adjacent bias"),adjacentBias->GetValue() / 100.0);
Options.SetBool(_T("Timing processor Enable lead-in"),hasLeadIn->IsChecked());
Options.SetBool(_T("Timing processor Enable lead-out"),hasLeadOut->IsChecked());
if (keysEnable->IsEnabled()) Options.SetBool(_T("Timing processor Enable keyframe"),keysEnable->IsChecked());
Options.SetBool(_T("Timing processor Enable adjacent"),adjsEnable->IsChecked());
Options.SetBool(_T("Timing processor Only Selection"),onlySelection->IsChecked());
Options.Save();
OPT_SET("Tool/Timing Post Processor/Threshold/Adjacent")->SetInt(temp);
OPT_SET("Tool/Timing Post Processor/Adjacent Bias")->SetDouble(adjacentBias->GetValue() / 100.0);
OPT_SET("Tool/Timing Post Processor/Enable/Lead/IN")->SetBool(hasLeadIn->IsChecked());
OPT_SET("Tool/Timing Post Processor/Enable/Lead/OUT")->SetBool(hasLeadOut->IsChecked());
if (keysEnable->IsEnabled()) OPT_SET("Tool/Timing Post Processor/Enable/Keyframe")->SetBool(keysEnable->IsChecked());
OPT_SET("Tool/Timing Post Processor/Enable/Adjacent")->SetBool(adjsEnable->IsChecked());
OPT_SET("Tool/Timing Post Processor/Only Selection")->SetBool(onlySelection->IsChecked());
// Check if rows are valid
bool valid = true;

View file

@ -45,6 +45,7 @@
#endif
#include "dialog_tip.h"
#include "main.h"
#include "options.h"
@ -99,12 +100,11 @@ wxString TipOfTheDay::GetTip() {
///
void TipOfTheDay::Show(wxWindow *parent) {
try {
if (Options.AsBool(_T("Tips enabled"))) {
TipOfTheDay *tip = new TipOfTheDay(Options.AsInt(_T("Tips current")));
if (OPT_GET("App/Tips")->GetBool()) {
TipOfTheDay *tip = new TipOfTheDay(OPT_GET("Tool/Tip of the Day/Current")->GetInt());
bool show = wxShowTip(parent, tip, true);
if (!show) Options.SetBool(_T("Tips enabled"),false);
Options.SetInt(_T("Tips current"),tip->curTip);
Options.Save();
if (!show) OPT_SET("App/Tips")->SetBool(false);
OPT_SET("Tool/Tip of the Day/Current")->SetInt(tip->curTip);
delete tip;
}
}

View file

@ -64,12 +64,14 @@
#include <vector>
#endif
#include "compat.h"
#include "dialog_version_check.h"
#include "main.h"
#include "options.h"
#include "include/aegisub/exception.h"
#include "string_codec.h"
#include "version.h"
#include <libaegisub/exception.h>
/* *** Public API is implemented here *** */
@ -138,7 +140,7 @@ public:
};
DEFINE_SIMPLE_EXCEPTION_NOINNER(VersionCheckError, Aegisub::Exception, "versioncheck")
DEFINE_SIMPLE_EXCEPTION_NOINNER(VersionCheckError, agi::Exception, "versioncheck")
class AegisubVersionCheckEventHandler : public wxEvtHandler {
@ -169,11 +171,11 @@ wxThread::ExitCode AegisubVersionCheckerThread::Entry()
if (!interactive)
{
// Automatic checking enabled?
if (!Options.AsBool(_T("auto check for updates")))
if (!OPT_GET("App/Auto/Check For Updates")->GetInt())
return 0;
// Is it actually time for a check?
time_t next_check = Options.AsInt(_T("Updates Next Check Time"));
time_t next_check = OPT_GET("Version/Next Check")->GetInt();
if ((time_t)next_check > wxDateTime::GetTimeNow())
return 0;
}
@ -183,10 +185,10 @@ wxThread::ExitCode AegisubVersionCheckerThread::Entry()
try {
DoCheck();
}
catch (const Aegisub::Exception &e) {
catch (const agi::Exception &e) {
PostErrorEvent(wxString::Format(
_("There was an error checking for updates to Aegisub:\n%s\n\nIf other applications can access the Internet fine, this is probably a temporary server problem on our end."),
e.GetMessage().c_str()));
e.GetMessage()));
}
catch (...) {
PostErrorEvent(_("An unknown error occurred while checking for updates to Aegisub."));
@ -201,7 +203,7 @@ wxThread::ExitCode AegisubVersionCheckerThread::Entry()
// because the tree only depends on the keys.
// Lastly, writing options to disk only happens when Options.Save() is called.
time_t new_next_check_time = wxDateTime::GetTimeNow() + 60*60; // in one hour
Options.SetInt(_T("Updates Next Check Time"), (int)new_next_check_time);
OPT_SET("Version/Next Check")->SetInt((int)new_next_check_time);
return 0;
}
@ -338,12 +340,14 @@ void AegisubVersionCheckerThread::DoCheck()
http.SetFlags(wxSOCKET_WAITALL|wxSOCKET_BLOCK);
if (!http.Connect(servername))
throw VersionCheckError(_("Could not connect to updates server."));
throw VersionCheckError(STD_STR(_("Could not connect to updates server.")));
std::auto_ptr<wxInputStream> stream(http.GetInputStream(path));
if (http.GetResponse() < 200 || http.GetResponse() >= 300)
throw VersionCheckError(wxString::Format(_("HTTP request failed, got HTTP response %d."), http.GetResponse()));
if (http.GetResponse() < 200 || http.GetResponse() >= 300) {
const std::string str_err = STD_STR(wxString::Format(_("HTTP request failed, got HTTP response %d."), http.GetResponse()));
throw VersionCheckError(str_err);
}
wxTextInputStream text(*stream);
@ -485,7 +489,7 @@ VersionCheckerResultDialog::VersionCheckerResultDialog(const wxString &main_text
}
automatic_check_checkbox = new wxCheckBox(this, -1, _("Auto Check for Updates"));
automatic_check_checkbox->SetValue(Options.AsBool(_T("Auto check for updates")));
automatic_check_checkbox->SetValue(!!OPT_GET("App/Auto/Check For Updates")->GetInt());
wxButton *remind_later_button = 0;
if (updates.size() > 0)
@ -523,7 +527,7 @@ void VersionCheckerResultDialog::OnRemindMeLater(wxCommandEvent &evt)
{
// In one week
time_t new_next_check_time = wxDateTime::Today().GetTicks() + 7*24*60*60;
Options.SetInt(_T("Updates Next Check Time"), (int)new_next_check_time);
OPT_SET("Version/Next Check")->SetInt((int)new_next_check_time);
Close();
}
@ -531,7 +535,7 @@ void VersionCheckerResultDialog::OnRemindMeLater(wxCommandEvent &evt)
void VersionCheckerResultDialog::OnClose(wxCloseEvent &evt)
{
Options.SetBool(_T("Auto check for updates"), automatic_check_checkbox->GetValue());
OPT_SET("App/Auto/Check For Updates")->SetBool(automatic_check_checkbox->GetValue());
Destroy();
}

View file

@ -46,6 +46,7 @@
#include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
#endif
#include "compat.h"
#include "ffmpegsource_common.h"
#include "frame_main.h"
#include "main.h"
@ -176,7 +177,7 @@ int FFmpegSourceProvider::AskForTrackSelection(const std::map<int,wxString> &Tra
/// @brief Set ffms2 log level according to setting in config.dat
void FFmpegSourceProvider::SetLogLevel() {
wxString LogLevel = Options.AsText(_T("FFmpegSource log level"));
wxString LogLevel = lagi_wxString(OPT_GET("Provider/FFmpegSource/Log Level")->GetString());
if (!LogLevel.CmpNoCase(_T("panic")))
FFMS_SetLogLevel(FFMS_LOG_PANIC);
@ -198,7 +199,7 @@ void FFmpegSourceProvider::SetLogLevel() {
FFMS_IndexErrorHandling FFmpegSourceProvider::GetErrorHandlingMode() {
wxString Mode = Options.AsText(_T("FFmpegSource audio decoding error handling"));
wxString Mode = lagi_wxString(OPT_GET("Provider/Audio/FFMpegSource/Decode Error Handling")->GetString());
if (!Mode.CmpNoCase(_T("ignore")))
return FFMS_IEH_IGNORE;
@ -310,9 +311,9 @@ wxThread::ExitCode FFmpegSourceCacheCleaner::Entry() {
// the option is in megabytes, we need bytes
// shift left by 20 is CLEARLY more efficient than multiplying by 1048576
int64_t maxsize = Options.AsInt(_T("FFmpegSource max cache size")) << 20;
int64_t maxsize = OPT_GET("Provider/FFmpegSource/Cache/Size")->GetInt() << 20;
int64_t cursize = wxDir::GetTotalSize(cachedirname).GetValue();
int maxfiles = Options.AsInt(_T("FFmpegSource max cache files"));
int maxfiles = OPT_GET("Provider/FFmpegSource/Cache/Files")->GetInt();
if (!cachedir.HasFiles(_T("*.ffindex"))) {
wxLogDebug(_T("FFmpegSourceCacheCleaner: no index files in cache folder, exiting"));

View file

@ -62,6 +62,7 @@
#include "avisynth_wrap.h"
#endif
#include "charset_conv.h"
#include "compat.h"
#include "dialog_detached_video.h"
#include "dialog_search_replace.h"
#include "dialog_splash.h"
@ -145,7 +146,7 @@ FrameMain::FrameMain (wxArrayString args)
// Create menu and tool bars
StartupLog(_T("Apply saved Maximized state"));
if (Options.AsBool(_T("Maximized"))) Maximize(true);
if (OPT_GET("App/Maximized")->GetBool()) Maximize(true);
StartupLog(_T("Initialize toolbar"));
InitToolbar();
StartupLog(_T("Initialize menu bar"));
@ -179,7 +180,7 @@ FrameMain::FrameMain (wxArrayString args)
// It doesn't work properly on wxMac, and the jumping dock icon
// signals the same as the splash screen either way.
#if !_DEBUG && !__WXMAC__
if (Options.AsBool(_T("Show Splash"))) {
if (OPT_GET("App/Splash")->GetBool()) {
SplashScreen *splash = new SplashScreen(this);
splash->Show(true);
splash->Update();
@ -192,7 +193,7 @@ FrameMain::FrameMain (wxArrayString args)
// Set autosave timer
StartupLog(_T("Set up Auto Save"));
AutoSave.SetOwner(this,AutoSave_Timer);
int time = Options.AsInt(_T("Auto save every seconds"));
int time = OPT_GET("App/Auto/Save Every Seconds")->GetInt();
if (time > 0) {
AutoSave.Start(time*1000);
}
@ -214,12 +215,11 @@ FrameMain::FrameMain (wxArrayString args)
// Version checker
StartupLog(_T("Possibly perform automatic updates check"));
int option = Options.AsInt(_T("Auto check for updates"));
int option = OPT_GET("App/Auto/Check For Updates")->GetInt();
if (option == -1) {
int result = wxMessageBox(_("Do you want Aegisub to check for updates whenever it starts? You can still do it manually via the Help menu."),_("Check for updates?"),wxYES_NO);
option = (result == wxYES);
Options.SetInt(_T("Auto check for updates"),option);
Options.Save();
OPT_SET("App/Auto/Check For Updates")->SetInt(option);
}
PerformVersionCheck(false);
@ -609,7 +609,7 @@ void FrameMain::InitContents() {
videoBox->videoSlider->grid = SubsBox;
VideoContext::Get()->grid = SubsBox;
StartupLog(_T("Reset video zoom"));
videoBox->videoDisplay->SetZoom(Options.AsInt(_T("Video Default Zoom")) * .125 + .125);
videoBox->videoDisplay->SetZoom(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125);
Search.grid = SubsBox;
// Audio area
@ -718,7 +718,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
wxString cur = testSubs.ReadLineFromFile();
if (cur.Left(10) == _T("# timecode")) {
LoadVFR(filename);
Options.SetText(_T("Last open timecodes path"), fileCheck.GetPath());
OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(fileCheck.GetPath()));
return;
}
}
@ -737,7 +737,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
SubsBox->LoadFromAss(AssFile::top,false,true);
wxFileName fn(filename);
StandardPaths::SetPathValue(_T("?script"),fn.GetPath());
Options.SetText(_T("Last open subtitles path"), fn.GetPath());
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(fn.GetPath()));
}
else {
SubsBox->LoadDefault(AssFile::top);
@ -759,9 +759,9 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
// Save copy
wxFileName origfile(filename);
if (!isBinary && Options.AsBool(_T("Auto backup")) && origfile.FileExists()) {
if (!isBinary && OPT_GET("App/Auto/Backup")->GetBool() && origfile.FileExists()) {
// Get path
wxString path = Options.AsText(_T("Auto backup path"));
wxString path = lagi_wxString(OPT_GET("Path/Auto/Backup")->GetString());
if (path.IsEmpty()) path = origfile.GetPath();
wxFileName dstpath(path);
if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
@ -796,7 +796,7 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
// Failed, ask user
if (filename.IsEmpty()) {
VideoContext::Get()->Stop();
wxString path = Options.AsText(_T("Last open subtitles path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
wxFileName origPath(AssFile::top->filename);
filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this);
}
@ -805,7 +805,7 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
if (!filename.empty()) {
// Store path
wxFileName filepath(filename);
Options.SetText(_T("Last open subtitles path"), filepath.GetPath());
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
// Fix me, ghetto hack for correct relative path generation in SynchronizeProject()
AssFile::top->filename = filename;
@ -979,7 +979,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
wxString AutoScriptString = subs->GetScriptInfo(_T("Automation Scripts"));
// Check if there is anything to change
int autoLoadMode = Options.AsInt(_T("Autoload linked files"));
int autoLoadMode = OPT_GET("App/Auto/Load Linked Files")->GetInt();
bool hasToLoad = false;
if (curSubsAudio != audioBox->audioName ||
curSubsVFR != VFR_Output.GetFilename() ||
@ -1034,7 +1034,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
local_scripts->RemoveAll();
wxStringTokenizer tok(AutoScriptString, _T("|"), wxTOKEN_STRTOK);
wxFileName subsfn(subs->filename);
wxString autobasefn(Options.AsText(_T("Automation Base Path")));
wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString()));
while (tok.HasMoreTokens()) {
wxString sfnames = tok.GetNextToken().Trim(true).Trim(false);
wxString sfnamel = sfnames.Left(1);
@ -1102,7 +1102,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
// 4. Otherwise, use path relative to subs ("~")
#ifdef WITH_AUTOMATION
wxString scripts_string;
wxString autobasefn(Options.AsText(_T("Automation Base Path")));
wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString()));
const std::vector<Automation4::Script*> &scripts = local_scripts->GetScripts();
for (unsigned int i = 0; i < scripts.size(); i++) {
@ -1182,7 +1182,7 @@ void FrameMain::LoadVideo(wxString file,bool autoload) {
int scriptx = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResX"));
int scripty = SubsBox->ass->GetScriptInfoAsInt(_T("PlayResY"));
if (scriptx != vidx || scripty != vidy) {
switch (Options.AsInt(_T("Video Check Script Res"))) {
switch (OPT_GET("Video/Check Script Res")->GetInt()) {
case 1:
// Ask to change on mismatch
if (wxMessageBox(wxString::Format(_("The resolution of the loaded video and the resolution specified for the subtitles don't match.\n\nVideo resolution:\t%d x %d\nScript resolution:\t%d x %d\n\nChange subtitles resolution to match video?"), vidx, vidy, scriptx, scripty), _("Resolution mismatch"), wxYES_NO, this) != wxYES)
@ -1207,7 +1207,7 @@ void FrameMain::LoadVideo(wxString file,bool autoload) {
SetDisplayMode(1,-1);
EditBox->UpdateFrameTiming();
DetachVideo(VideoContext::Get()->IsLoaded() && Options.AsBool(_T("Detached Video")));
DetachVideo(VideoContext::Get()->IsLoaded() && OPT_GET("Video/Detached/Enabled")->GetBool());
Thaw();
}
@ -1345,7 +1345,7 @@ void FrameMain::SetAccelerators() {
entry.push_back(Hotkeys.GetAccelerator(_T("Edit box commit"),Edit_Box_Commit));
// Medusa
bool medusaPlay = Options.AsBool(_T("Audio Medusa Timing Hotkeys"));
bool medusaPlay = OPT_GET("Audio/Medusa Timing Hotkeys")->GetBool();
if (medusaPlay && audioBox->audioDisplay->loaded) {
entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Play"),Medusa_Play));
entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Stop"),Medusa_Stop));

View file

@ -295,7 +295,7 @@ private:
void OnOpenVideoDetails (wxCommandEvent &event);
void OnOpenASSDraw (wxCommandEvent &event);
void OnOpenOptions (wxCommandEvent &event);
void OnOpenPreferences (wxCommandEvent &event);
void OnGridEvent (wxCommandEvent &event);
void OnOpenAutomation (wxCommandEvent &event);

View file

@ -57,6 +57,7 @@
#include "auto4_base.h"
#endif
#include "charset_conv.h"
#include "compat.h"
#include "dialog_about.h"
#include "dialog_attachments.h"
#include "dialog_automation.h"
@ -65,7 +66,6 @@
#include "dialog_fonts_collector.h"
#include "dialog_jumpto.h"
#include "dialog_kara_timing_copy.h"
#include "dialog_options.h"
#include "dialog_progress.h"
#include "dialog_properties.h"
#include "dialog_resample.h"
@ -80,10 +80,12 @@
#include "dialog_version_check.h"
#include "dialog_video_details.h"
#include "frame_main.h"
#include "hotkeys.h"
#include "keyframe.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "preferences.h"
#include "standard_paths.h"
#include "subs_edit_box.h"
#include "subs_grid.h"
@ -192,7 +194,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame)
EVT_MENU(Menu_Tools_Resample, FrameMain::OnOpenResample)
EVT_MENU(Menu_Tools_Timing_Processor, FrameMain::OnOpenTimingProcessor)
EVT_MENU(Menu_Tools_Kanji_Timer, FrameMain::OnOpenKanjiTimer)
EVT_MENU(Menu_Tools_Options, FrameMain::OnOpenOptions)
EVT_MENU(Menu_Tools_Options, FrameMain::OnOpenPreferences)
EVT_MENU(Menu_Tools_ASSDraw, FrameMain::OnOpenASSDraw)
EVT_MENU(Menu_Subs_Snap_Start_To_Video, FrameMain::OnSnapSubsStartToVid)
@ -272,7 +274,7 @@ void FrameMain::RebuildRecentList(wxString listName,wxMenu *menu,int startID) {
// Rebuild
int added = 0;
wxString n;
wxArrayString entries = Options.GetRecentList(listName);
wxArrayString entries = lagi_MRU_wxAS(listName);
for (size_t i=0;i<entries.Count();i++) {
n = wxString::Format(_T("%i"),i+1);
if (i < 9) n = _T("&") + n;
@ -299,7 +301,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
// File menu
if (curMenu == fileMenu) {
// Rebuild recent
RebuildRecentList(_T("Recent sub"),RecentSubs,Menu_File_Recent);
RebuildRecentList(_T("Subtitle"),RecentSubs,Menu_File_Recent);
MenuBar->Enable(Menu_File_Open_Subtitles_From_Video,VideoContext::Get()->HasSubtitles());
}
@ -321,7 +323,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
else if (showAudio && showVideo) MenuBar->Check(Menu_View_Standard,true);
else MenuBar->Check(Menu_View_Audio,true);
MenuBar->Check(Options.AsInt(L"Grid hide overrides") + Menu_View_FullTags, true);
MenuBar->Check(OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt() + Menu_View_FullTags, true);
}
// Video menu
@ -368,12 +370,12 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
}
// Set overscan mask
MenuBar->Check(Menu_Video_Overscan,Options.AsBool(_T("Show Overscan Mask")));
MenuBar->Check(Menu_Video_Overscan,OPT_GET("Video/Overscan Mask")->GetBool());
// Rebuild recent lists
RebuildRecentList(_T("Recent vid"),RecentVids,Menu_Video_Recent);
RebuildRecentList(_T("Recent timecodes"),RecentTimecodes,Menu_Timecodes_Recent);
RebuildRecentList(_T("Recent Keyframes"),RecentKeyframes,Menu_Keyframes_Recent);
RebuildRecentList(_T("Video"),RecentVids,Menu_Video_Recent);
RebuildRecentList(_T("Timecodes"),RecentTimecodes,Menu_Timecodes_Recent);
RebuildRecentList(_T("Keyframes"),RecentKeyframes,Menu_Keyframes_Recent);
}
// Audio menu
@ -385,7 +387,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
MenuBar->Enable(Menu_Audio_Close,state);
// Rebuild recent
RebuildRecentList(_T("Recent aud"),RecentAuds,Menu_Audio_Recent);
RebuildRecentList(_T("Audio"),RecentAuds,Menu_Audio_Recent);
}
// Subtitles menu
@ -534,8 +536,7 @@ int FrameMain::AddMacroMenuItems(wxMenu *menu, const std::vector<Automation4::Fe
///
void FrameMain::OnOpenRecentSubs(wxCommandEvent &event) {
int number = event.GetId()-Menu_File_Recent;
wxString key = _T("Recent sub #") + wxString::Format(_T("%i"),number+1);
LoadSubtitles(Options.AsText(key));
LoadSubtitles(AegisubApp::Get()->mru->GetEntry("Subtitle", number));
}
@ -545,8 +546,7 @@ void FrameMain::OnOpenRecentSubs(wxCommandEvent &event) {
///
void FrameMain::OnOpenRecentVideo(wxCommandEvent &event) {
int number = event.GetId()-Menu_Video_Recent;
wxString key = _T("Recent vid #") + wxString::Format(_T("%i"),number+1);
LoadVideo(Options.AsText(key));
LoadSubtitles(AegisubApp::Get()->mru->GetEntry("Video", number));
}
@ -556,8 +556,7 @@ void FrameMain::OnOpenRecentVideo(wxCommandEvent &event) {
///
void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
int number = event.GetId()-Menu_Timecodes_Recent;
wxString key = _T("Recent timecodes #") + wxString::Format(_T("%i"),number+1);
LoadVFR(Options.AsText(key));
LoadSubtitles(AegisubApp::Get()->mru->GetEntry("Timecodes", number));
}
@ -567,8 +566,7 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
///
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
int number = event.GetId()-Menu_Keyframes_Recent;
wxString key = _T("Recent Keyframes #") + wxString::Format(_T("%i"),number+1);
KeyFrameFile::Load(Options.AsText(key));
LoadSubtitles(AegisubApp::Get()->mru->GetEntry("Keyframes", number));
videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update();
Refresh();
@ -581,8 +579,7 @@ void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
///
void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) {
int number = event.GetId()-Menu_Audio_Recent;
wxString key = _T("Recent aud #") + wxString::Format(_T("%i"),number+1);
LoadAudio(Options.AsText(key));
LoadSubtitles(AegisubApp::Get()->mru->GetEntry("Audio", number));
}
@ -706,14 +703,13 @@ void FrameMain::OnVideoPlay(wxCommandEvent &event) {
/// @param event
///
void FrameMain::OnOpenVideo(wxCommandEvent& WXUNUSED(event)) {
wxString path = Options.AsText(_T("Last open video path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Video")->GetString());
wxString str = wxString(_("Video Formats")) + _T(" (*.avi,*.mkv,*.mp4,*.avs,*.d2v,*.ogm,*.mpeg,*.mpg,*.vob,*.mov)|*.avi;*.avs;*.d2v;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg;*.vob;*.mov|")
+ _("All Files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Open video file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.empty()) {
LoadVideo(filename);
Options.SetText(_T("Last open video path"), filename);
Options.Save();
OPT_SET("Path/Last/Video")->SetString(STD_STR(filename));
}
}
@ -732,15 +728,14 @@ void FrameMain::OnCloseVideo(wxCommandEvent& WXUNUSED(event)) {
/// @param event
///
void FrameMain::OnOpenAudio (wxCommandEvent& WXUNUSED(event)) {
wxString path = Options.AsText(_T("Last open audio path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Audio")->GetString());
wxString str = wxString(_("Audio Formats")) + _T(" (*.wav,*.mp3,*.ogg,*.flac,*.mp4,*.ac3,*.aac,*.mka,*.m4a,*.w64)|*.wav;*.mp3;*.ogg;*.flac;*.mp4;*.ac3;*.aac;*.mka;*.m4a;*.w64|")
+ _("Video Formats") + _T(" (*.avi,*.mkv,*.ogm,*.mpg,*.mpeg)|*.avi;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg|")
+ _("All files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Open audio file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.empty()) {
LoadAudio(filename);
Options.SetText(_T("Last open audio path"), filename);
Options.Save();
OPT_SET("Path/Last/Audio")->SetString(STD_STR(filename));
}
}
@ -785,13 +780,12 @@ void FrameMain::OnOpenDummyNoiseAudio (wxCommandEvent& WXUNUSED(event)) {
/// @param event
///
void FrameMain::OnOpenSubtitles(wxCommandEvent& WXUNUSED(event)) {
wxString path = Options.AsText(_T("Last open subtitles path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.empty()) {
LoadSubtitles(filename);
wxFileName filepath(filename);
Options.SetText(_T("Last open subtitles path"), filepath.GetPath());
Options.Save();
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
}
}
@ -803,7 +797,7 @@ void FrameMain::OnOpenSubtitles(wxCommandEvent& WXUNUSED(event)) {
void FrameMain::OnOpenSubtitlesCharset(wxCommandEvent& WXUNUSED(event)) {
// Initialize charsets
wxArrayString choices = AegisubCSConv::GetEncodingsList();
wxString path = Options.AsText(_T("Last open subtitles path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
// Get options and load
wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -812,8 +806,7 @@ void FrameMain::OnOpenSubtitlesCharset(wxCommandEvent& WXUNUSED(event)) {
if (!charset.empty()) {
LoadSubtitles(filename,charset);
}
Options.SetText(_T("Last open subtitles path"), filename);
Options.Save();
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filename));
}
}
@ -865,7 +858,7 @@ void FrameMain::OnNewSubtitles(wxCommandEvent& WXUNUSED(event)) {
///
void FrameMain::OnExportSubtitles(wxCommandEvent & WXUNUSED(event)) {
#ifdef WITH_AUTOMATION
int autoreload = Options.AsInt(_T("Automation Autoreload Mode"));
int autoreload = OPT_GET("Automation/Autoreload Mode")->GetInt();
if (autoreload & 1) {
// Local scripts
const std::vector<Automation4::Script*> scripts = local_scripts->GetScripts();
@ -897,14 +890,13 @@ void FrameMain::OnExportSubtitles(wxCommandEvent & WXUNUSED(event)) {
/// @param event
///
void FrameMain::OnOpenVFR(wxCommandEvent &event) {
wxString path = Options.AsText(_T("Last open timecodes path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString());
wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|")
+ _("All Files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Open timecodes file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.empty()) {
LoadVFR(filename);
Options.SetText(_T("Last open timecodes path"), filename);
Options.Save();
OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename));
}
}
@ -914,14 +906,13 @@ void FrameMain::OnOpenVFR(wxCommandEvent &event) {
/// @param event
///
void FrameMain::OnSaveVFR(wxCommandEvent &event) {
wxString path = Options.AsText(_T("Last open timecodes path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString());
wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|")
+ _("All Files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (!filename.empty()) {
SaveVFR(filename);
Options.SetText(_T("Last open timecodes path"), filename);
Options.Save();
OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename));
}
}
@ -943,11 +934,10 @@ void FrameMain::OnCloseVFR(wxCommandEvent &event) {
///
void FrameMain::OnOpenKeyframes (wxCommandEvent &event) {
// Pick file
wxString path = Options.AsText(_T("Last open keyframes path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString());
wxString filename = wxFileSelector(_T("Select the keyframes file to open"),path,_T(""),_T(".txt"),_T("All supported formats (*.txt, *.pass, *.stats, *.log)|*.txt;*.pass;*.stats;*.log|All files (*.*)|*.*"),wxFD_FILE_MUST_EXIST | wxFD_OPEN);
if (filename.IsEmpty()) return;
Options.SetText(_T("Last open keyframes path"),filename);
Options.Save();
OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename));
// Load
KeyFrameFile::Load(filename);
@ -976,11 +966,10 @@ void FrameMain::OnCloseKeyframes (wxCommandEvent &event) {
///
void FrameMain::OnSaveKeyframes (wxCommandEvent &event) {
// Pick file
wxString path = Options.AsText(_T("Last open keyframes path"));
wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString());
wxString filename = wxFileSelector(_T("Select the Keyframes file to open"),path,_T(""),_T("*.key.txt"),_T("Text files (*.txt)|*.txt"),wxFD_OVERWRITE_PROMPT | wxFD_SAVE);
if (filename.IsEmpty()) return;
Options.SetText(_T("Last open keyframes path"),filename);
Options.Save();
OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename));
// Save
KeyFrameFile::Save(filename);
@ -1067,8 +1056,7 @@ void FrameMain::OnDummyVideo (wxCommandEvent &event) {
/// @param event
///
void FrameMain::OnOverscan (wxCommandEvent &event) {
Options.SetBool(_T("Show overscan mask"),event.IsChecked());
Options.Save();
OPT_SET("Video/Overscan Mask")->SetBool(event.IsChecked());
VideoContext::Get()->Stop();
videoBox->videoDisplay->Render();
}
@ -1217,13 +1205,13 @@ void FrameMain::OnOpenKanjiTimer (wxCommandEvent &event) {
/// @brief Open Options dialog
/// @param event
///
void FrameMain::OnOpenOptions (wxCommandEvent &event) {
void FrameMain::OnOpenPreferences (wxCommandEvent &event) {
try {
DialogOptions options(this);
options.ShowModal();
}
catch (const wxChar *e) {
wxLogError(e);
Preferences pref(this);
pref.ShowModal();
} catch (agi::Exception& e) {
wxPrintf("Caught agi::Exception: %s -> %s\n", e.GetName(), e.GetMessage());
}
}
@ -1615,8 +1603,7 @@ void FrameMain::OnCloseWindow (wxCloseEvent &event) {
int result = TryToCloseSubs(canVeto);
// Store maximization state
Options.SetBool(_T("Maximized"),IsMaximized());
Options.Save();
OPT_SET("App/Maximized")->SetBool(IsMaximized());
// Abort/destroy
if (canVeto) {
@ -1738,7 +1725,7 @@ void FrameMain::OnAutoSave(wxTimerEvent &event) {
if (AssFile::top->loaded) {
// Set path
wxFileName origfile(AssFile::top->filename);
wxString path = Options.AsText(_T("Auto save path"));
wxString path = lagi_wxString(OPT_GET("Path/Auto/Save")->GetString());
if (path.IsEmpty()) path = origfile.GetPath();
wxFileName dstpath(path);
if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/"));
@ -1848,7 +1835,7 @@ void FrameMain::OnNextLine(wxCommandEvent &event) {
/// @brief Cycle through tag hiding modes
void FrameMain::OnToggleTags(wxCommandEvent &) {
int tagMode = Options.AsInt(_T("Grid hide overrides"));
int tagMode = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt();
// Cycle to next
tagMode = (tagMode+1)%3;
@ -1861,15 +1848,13 @@ void FrameMain::OnToggleTags(wxCommandEvent &) {
StatusTimeout(message,10000);
// Set option
Options.SetInt(_T("Grid hide overrides"),tagMode);
Options.Save();
OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(tagMode);
// Refresh grid
SubsBox->Refresh(false);
}
void FrameMain::OnSetTags(wxCommandEvent &event) {
Options.SetInt(_T("Grid hide overrides"), event.GetId() - Menu_View_FullTags);
Options.Save();
OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(event.GetId() - Menu_View_FullTags);
SubsBox->Refresh(false);
}
@ -1914,8 +1899,7 @@ void FrameMain::OnChooseLanguage (wxCommandEvent &event) {
// Is OK?
if (newCode != -1) {
// Set code
Options.SetInt(_T("Locale Code"),newCode);
Options.Save();
OPT_SET("App/Locale")->SetInt(newCode);
// Language actually changed?
if (newCode != old) {

View file

@ -39,7 +39,9 @@
// Includes
#include "config.h"
#include "compat.h"
#include "hilimod_textctrl.h"
#include "main.h"
#include "options.h"
@ -111,7 +113,7 @@ void HiliModTextCtrl::Modified() {
// Different from original
if (!isModified && !match) {
isModified = true;
SetBackgroundColour(Options.AsColour(_T("Edit Box Need Enter Background")));
SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour()));
Refresh(false);
}

View file

@ -42,7 +42,9 @@
#include <wx/msgdlg.h>
#endif
#include "compat.h"
#include "keyframe.h"
#include "main.h"
#include "options.h"
#include "text_file_reader.h"
#include "text_file_writer.h"
@ -74,7 +76,7 @@ void KeyFrameFile::Load(wxString filename) {
VideoContext::Get()->SetKeyFramesName(filename);
// Add to recent
Options.AddToRecentList(filename,_T("Recent keyframes"));
AegisubApp::Get()->mru->Add("Keyframes", STD_STR(filename));
}
// Fail
catch (const wchar_t *error) {
@ -106,7 +108,7 @@ void KeyFrameFile::Save(wxString filename) {
}
// Add to recent
Options.AddToRecentList(filename,_T("Recent keyframes"));
AegisubApp::Get()->mru->Add("Keyframes", STD_STR(filename));
}

View file

@ -9,10 +9,10 @@ BUILT_SOURCES = bitmap.cpp default_config.cpp
bitmap.cpp: ../../tools/common-respack
../../tools/common-respack bitmap.cpp ../bitmaps/16 ../bitmaps/24 ../bitmaps/misc/splash.png ../bitmaps/misc/wxicon.png
default_config.cpp: ../../tools/common-respack
../../tools/common-respack default_config.cpp ./default_mru.json
default_config.cpp: ../../tools/common-respack *.json
../../tools/common-respack default_config.cpp ./default_mru.json ./default_config.json
EXTRA_DIST = default_mru.json
EXTRA_DIST = *.json
CLEANFILES= \
bitmap.cpp \

View file

@ -0,0 +1,191 @@
Allow Ancient Avisynth Provider/Avisynth/Allow Ancient
Audio Alsa Device Player/Audio/ALSA/Device
Audio Autocommit Audio/Auto/Commit
Audio Autofocus Audio/Auto/Focus
Audio Autoscroll Audio/Auto/Scroll
Audio Background Colour/Audio Display/Background/Background
Audio Cache Audio/Cache/Type
Audio Disable PCM Provider Provider/Audio/PCM/Disable
Audio Display Height Audio/Display Height
Audio Downmixer Audio/Downmixer
Audio Draw Cursor Time Audio/Display/Draw/Cursor Time
Audio Draw Keyframes Audio/Display/Draw/Keyframes
Audio Draw Secondary Lines Audio/Display/Draw/Secondary Lines
Audio Draw Selection Background Audio/Display/Draw/Selection Background
Audio Draw Timeline Audio/Display/Draw/Timeline
Audio Draw Video Position Audio/Display/Draw/Video Position
Audio dsound buffer latency Player/Audio/DirectSound/Buffer Latency
Audio dsound buffer length Player/Audio/DirectSound/Buffer Length
Audio grab times on select Audio/Grab Times on Select
Audio HD Cache Location Audio/Cache/HD/Location
Audio HD Cache Name Audio/Cache/HD/Name
Audio Inactive Lines Display Mode Audio/Inactive Lines Display Mode
Audio Lead in Audio/Lead/IN
Audio Lead out Audio/Lead/OUT
Audio Line boundaries Thickness Audio/Line Boundaries Thickness
Audio Line boundary end Colour/Audio Display/Line boundary End
Audio Line boundary inactive line Colour/Audio Display/Line Boundary Inactive Line
Audio Line boundary start Colour/Audio Display/Line boundary Start
Audio Link Audio/Link
Audio lock scroll on cursor Audio/Lock Scroll on Cursor
Audio Medusa Timing Hotkeys Audio/Medusa Timing Hotkeys
Audio Next Line on Commit Audio/Next Line on Commit
Audio OSS Device Audio/OSS/Device
Audio Play Cursor Colour/Audio Display/Play Cursor
Audio player Audio/Player
Audio Plays When Stepping Video Audio/Plays When Stepping
Audio PortAudio Device Player/Audio/PortAudio/Device
Audio provider Audio/Provider
Audio Sample Rate Provider/Audio/AVS/Sample Rate
Audio Seconds Boundaries Colour/Audio Display/Seconds Boundaries
Audio Selection Background Colour/Audio Display/Background/Background
Audio Selection Background Modified Colour/Audio Display/Background/Selection Modified
Audio snap to keyframes Audio/Display/Snap/Keyframes
Audio snap to other lines Audio/Display/Snap/Other Lines
Audio Spectrum Audio/Spectrum
Audio Spectrum Cutoff Audio/Renderer/Spectrum/Cutoff
Audio Spectrum Memory Max Audio/Renderer/Spectrum/Memory Max
Audio Spectrum Quality Audio/Renderer/Spectrum/Quality
Audio Start Drag Sensitivity Audio/Start Drag Sensitivity
Audio Syllable boundaries Colour/Audio Display/Syllable Boundaries
Audio Syllable text Colour/Audio Display/Syllable Text
Audio Waveform Colour/Audio Display/Waveform
Audio Waveform Inactive Colour/Audio Display/Waveform Inactive
Audio Waveform Modified Colour/Audio Display/Waveform Modified
Audio Waveform Selected Colour/Audio Display/Waveform Selected
Audio Wheel Default To Zoom Audio/Wheel Default to Zoom
Auto backup App/Auto/Backup
Auto backup path Path/Auto/Backup
Auto check for updates App/Auto/Check For Updates
Auto save every seconds App/Auto/Save Every Seconds
Auto Save on Every Change App/Auto/Save on Every Change
Auto save path Path/Auto/Save
Autoload linked files App/Auto/Load Linked Files
Automation Autoload Path Path/Automation/Autoload
Automation Autoreload Mode Automation/Autoreload Mode
Automation Base Path Path/Automation/Base
Automation Include Path Path/Automation/Include
Automation Thread Priority Automation/Lua/Thread Priority
Automation Trace Level Automation/Trace Level
Avisynth MemoryMax Provider/Avisynth/Memory Max
Call tips enabled App/Call Tips
Color Picker Mode Tool/Colour Picker/Mode
Color Picker Recent Tool/Colour Picker/Recent
Colour/Subtitle/Syntax/Error Colour/Subtitle/Syntax/Background/Error
Detached Video Video/Detached/Enabled
Detached video last x Video/Detached/Last/X
Detached video last y Video/Detached/Last/Y
Detached video maximized Video/Detached/Maximized
Dictionaries path Path/Dictionary
Disable Dragging Times Audio/Display/Dragging Times
Edit Box Need Enter Background Color/Background/Modified
Edit Font Face Subtitle/Edit Box/Font Face
Edit Font Size Subtitle/Edit Box/Font Size
FFmpeg allow unsafe seeking Provider/Video/FFMpegSource/Unsafe Seeking
FFmpegSource always index all tracks Provider/FFmpegSource/Index All Tracks
FFmpegSource audio decoding error handling Provider/Audio/FFMpegSource/Decode Error Handling
FFmpegSource decoding threads Provider/Video/FFmpegSource/Decoding Threads
FFmpegSource log level Provider/FFmpegSource/Log Level
FFmpegSource max cache files Provider/FFmpegSource/Cache/Files
FFmpegSource max cache size Provider/FFmpegSource/Cache/Size
Find Affect Tool/Search Replace/Affect
Find Field Tool/Search Replace/Field
Find Match Case Tool/Search Replace/Match Case
Find RegExp Tool/Search Replace/RegExp
Find Update Video Tool/Search Replace/Video Update
Fonts Collector Action Tool/Fonts Collector/Action
Fonts Collector Destination Path/Fonts Collector Destination
Grid Active border Colour/Subtitle Grid/Active Border
Grid Allow Focus Subtitle/Grid/Focus Allow
Grid Background Colour/Subtitle Grid/Background/Background
Grid collision foreground Colour/Subtitle Grid/Collision
Grid Font Face Subtitle/Grid/Font Face
Grid font size Subtitle/Grid/Font Size
Grid Hide Overrides Subtitle/Grid/Hide Overrides
Grid hide overrides char Subtitle/Grid/Hide Overrides Char
Grid left column Colour/Subtitle Grid/Left Column
Grid lines Colour/Subtitle Grid/Lines
Grid selection background Colour/Subtitle Grid/Background/Selection
Grid selection foreground Colour/Subtitle Grid/Selection
Grid standard foreground Colour/Subtitle Grid/Standard
Highlight subs in frame Subtitle/Grid/Highlight Subtitles in Frame
Insert Mode on Time Boxes Subtitle/Time Edit/Insert Mode
kanji timer interpolation Tool/Kanji Timer/Interpolation
Last open audio path Path/Last/Audio
Last open automation path Path/Last/Automation
Last open keyframes path Path/Last/Keyframes
Last open subtitles path Path/Last/Subtitles
Last open timecodes path Path/Last/Timecodes
Last open video path Path/Last/Video
Link Time Boxes Commit Subtitle/Edit Box/Link Time Boxes Commit
Local config App/Local Config
Locale Code App/Locale
Maximized App/Maximized
Recent timecodes Timecodes
RGBAdjust Tool Tool/Colour Picker/RGBAdjust Tool
Save Charset App/Save Charset
Select Action Tool/Select/Action
Select Condition Tool/Select/Condition
Select Field Tool/Select/Field
Select Match case Tool/Select Lines/Match/Case
Select Match comments Tool/Select Lines/Match/Comment
Select Match dialogues Tool/Select Lines/Match/Dialogue
Select Mode Tool/Select/Mode
Select Text Tool/Select Lines/Text
Shift Times Affect Tool/Shift Times/Affect
Shift Times ByTime Tools/Shift Times/ByTime
Shift Times Direction Tools/Shift Times/Direction
Shift Times Length Tool/Shift Times/Length
Shift Times Type Tool/Shift Times/Type
Show keyframes on video slider Video/Slider/Show Keyframes
Show Overscan Mask Video/Overscan Mask
Show Splash App/Splash
Spell Checker Tool/Spell Checker/Backend
Spell checker Language Tool/Spell Checker/Language
Style editor preview background Colour/Style Editor/Background/Preview
Style editor preview text Tool/Style Editor/Preview Text
Subtitles provider Subtitle/Provider
Sync video with subs Video/Subtitle Sync
Syntax Highlight Brackets Colour/Subtitle/Syntax/Brackets
Syntax Highlight Enabled Subtitle/Highlight/Syntax
Syntax Highlight Error Syntax Highlight Error Background
Syntax Highlight Karaoke Template Colour/Subtitle/Syntax/Karaoke Template
Syntax Highlight Line Break Colour/Subtitle/Syntax/Line Break
Syntax Highlight Normal Colour/Subtitle/Syntax/Normal
Syntax Highlight Parameters Colour/Subtitle/Syntax/Parameters
Syntax Highlight Slashes Colour/Subtitle/Syntax/Slashes
Syntax Highlight Tags Colour/Subtitle/Syntax/Highlight Tags
Text actor separator Tool/Import/Text/Actor Separator
Text comment starter Tool/Import/Text/Comment Starter
Thesaurus Language Tool/Thesaurus/Language
Timing Default Duration Timing/Default Duration
Timing processor adjacent bias Tool/Timing Post Processor/Adjacent Bias
Timing processor adjacent thres Tool/Timing Post Processor/Threshold/Adjacent
Timing processor Enable adjacent Tool/Timing Post Processor/Enable/Adjacent
Timing processor Enable keyframe Tool/Timing Post Processor/Enable/Keyframe
Timing processor Enable lead-in Tool/Timing Post Processor/Enable/Lead/IN
Timing processor Enable lead-out Tool/Timing Post Processor/Enable/Lead/OUT
Timing processor key end after thres Tool/Timing Post Processor/Threshold/Key End After
Timing processor key end before thres Tool/Timing Post Processor/Threshold/Key End Before
Timing processor key start after thres Tool/Timing Post Processor/Threshold/Key Start After
Timing processor key start before thres Tool/Timing Post Processor/Threshold/Key Start Before
Timing processor Only Selection Tool/Timing Post Processor/Only Selection
Tips current Tool/Tip of the Day/Current
Tips enabled App/Tips
Undo levels Subtitle/Undo Levels
Updates Next Check Time Version/Next Check
Use nonstandard Milisecond Times App/Nonstandard Milisecond Times
Video Check Script Res Video/Check Script Res
Video Default Zoom Video/Default Zoom
Video Dummy Last Colour Colour/Video Dummy/Last Colour
Video Dummy Last FPS Video/Dummy/FPS
Video Dummy Last Height Video/Dummy/Last/Height
Video Dummy Last Length Video/Dummy/Last/Length
Video Dummy Last Width Video/Dummy/Last/Width
Video Dummy Pattern Video/Dummy/Pattern
Video Fast Jump Step Video/Slider/Fast Jump Step
Video provider Video/Provider
Video Screenshot Path Path/Screenshot
Video Visual Realtime Video/Visual Realtime

View file

@ -0,0 +1,415 @@
{
"App" : {
"Auto" : {
"Backup" : true,
"Check For Updates" : -1,
"Load Linked Files" : 2,
"Save Every Seconds" : 60,
"Save on Every Change" : false
},
"Call Tips" : false,
"Local Config" : false,
"Locale" : -1,
"Maximized" : false,
"Nonstandard Milisecond Times" : false,
"Save Charset" : "UTF-8",
"Splash" : true,
"Tips" : false
},
"Audio" : {
"Auto" : {
"Commit" : false,
"Focus" : false,
"Scroll" : true
},
"Cache" : {
"HD" : {
"Location" : "default",
"Name" : "audio%02i.tmp"
},
"Type" : 1
},
"Display Height" : 200,
"Display" : {
"Dragging Times" : false,
"Draw" : {
"Cursor Time" : true,
"Keyframes" : true,
"Secondary Lines" : true,
"Selection Background" : true,
"Timeline" : true,
"Video Position" : false
},
"Snap" : {
"Keyframes" : false,
"Other Lines" : false
}
},
"Downmixer" : "ConvertToMono",
"Grab Times on Select" : true,
"Inactive Lines Display Mode" : 1,
"Lead" : {
"IN" : 200,
"OUT" : 300
},
"Line Boundaries Thickness" : 2,
"Line Boundary Inactive Line" : "grey",
"Link" : true,
"Lock Scroll on Cursor" : false,
"Medusa Timing Hotkeys" : false,
"Next Line on Commit" : true,
"Player" : "portaudio",
"Plays When Stepping Video" : false,
"Provider" : "ffmpegsource",
"Renderer" : {
"Spectrum" : {
"Cutoff" : 0,
"Memory Max" : 128,
"Quality" : 1
}
},
"Spectrum" : true,
"Start Drag Sensitivity" : 2,
"Wheel Default to Zoom" : false
},
"Automation" : {
"Autoreload Mode" : 1,
"Lua" : {
"Thread Priority" : 1
},
"Trace Level" : 3
},
"Colour" : {
"Audio Display" : {
"Background" : {
"Background" : "rgb(0,0,0)",
"Selection" : "rgb(64, 64, 64)",
"Selection Modified" : "rgb(92, 0, 0)"
},
"Line Boundary Inactive Line" : "rgb(190,190,190)",
"Line boundary End" : "rgb(230, 125, 0)",
"Line boundary Start" : "rgb(216, 0, 0)",
"Play Cursor" : "rgb(255,255,255)",
"Seconds Boundaries" : "rgb(0, 100, 255)",
"Syllable Boundaries" : "rgb(255,255,0)",
"Syllable Text" : "rgb(255,0,0)",
"Waveform" : "rgb(0, 200, 0)",
"Waveform Inactive" : "rgb(0, 80, 0)",
"Waveform Modified" : "rgb(255, 230, 230)",
"Waveform Selected" : "rgb(255,255,255)"
},
"Background" : {
"Modified" : "rgb(192, 192, 255)"
},
"Style Editor" : {
"Background" : {
"Preview" : "rgb(125, 153, 176)"
}
},
"Subtitle Grid" : {
"Active Border" : "rgb(255, 91, 239)",
"Background" : {
"Background" : "rgb(255,255,255)",
"Comment" : "rgb(216, 222, 245)",
"Inframe" : "rgb(255, 253, 234)",
"Selected Comment" : "rgb(211, 238, 238)",
"Selection" : "rgb(206, 255, 231)"
},
"Collision" : "rgb(255,0,0)",
"Header" : "rgb(165, 207, 231)",
"Left Column" : "rgb(196, 236, 201)",
"Lines" : "rgb(190,190,190)",
"Selection" : "rgb(0,0,0)",
"Standard" : "rgb(0,0,0)"
},
"Subtitle" : {
"Syntax" : {
"Background" : {
"Error" : "rgb(255, 200, 200)"
},
"Brackets" : "rgb(20, 50, 255)",
"Error" : "rgb(200, 0, 0)",
"Highlight Tags" : "rgb(90, 90, 90)",
"Karaoke Template" : "rgb(128, 0, 192)",
"Line Break" : "rgb(160, 160, 160)",
"Normal" : "rgb(0,0,0)",
"Parameters" : "rgb(40, 90, 40)",
"Slashes" : "rgb(255, 0, 200)"
}
},
"Video Dummy" : {
"Last Colour" : "rgb(47, 163, 254)"
}
},
"Limits" : {
"Find Replace" : 16,
"MRU" : 16,
"Undo Levels" : 8
},
"Path" : {
"Auto" : {
"Backup" : "?user/autoback",
"Save" : "?user/autosave"
},
"Automation" : {
"Autoload" : "?user/automation/autoload/|?data/automation/autoload/",
"Base" : "?data/automation/",
"Include" : "?user/automation/include/|?data/automation/include/"
},
"Dictionary" : "?user/dictionary",
"Fonts Collector Destination" : "?script",
"Last" : {
"Audio" : "",
"Automation" : "",
"Keyframes" : "",
"Subtitles" : "",
"Timecodes" : "",
"Video" : ""
},
"Screenshot" : "?video"
},
"Player" : {
"Audio" : {
"ALSA" : {
"Device" : "default"
},
"DirectSound" : {
"Buffer Latency" : 100,
"Buffer Length" : 5
},
"OSS" : {
"Device" : "/dev/dsp"
},
"PortAudio" : {
"Device" : -1
}
}
},
"Provider" : {
"Audio" : {
"AVS" : {
"Sample Rate" : 0
},
"FFMpegSource" : {
"Decode Error Handling" : "stop"
},
"PCM" : {
"Disable" : false
}
},
"Avisynth" : {
"Allow Ancient" : false,
"Memory Max" : 64
},
"FFmpegSource" : {
"Cache" : {
"Files" : 20,
"Size" : 42
},
"Index All Tracks" : true,
"Log Level" : "quiet"
},
"Video" : {
"Cache" : {
"Size" : 32
},
"FFMpegSource" : {
"Decoding Threads" : 1,
"Unsafe Seeking" : false
}
}
},
"Subtitle" : {
"Edit Box" : {
"Font Face" : "",
"Font Size" : 10,
"Link Time Boxes Commit" : true
},
"Grid" : {
"Column" : [
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true},
{"bool" : true}
],
"Focus Allow" : true,
"Font Face" : "",
"Font Size" : 10,
"Hide Overrides" : 1,
"Hide Overrides Char" : "☀",
"Highlight Subtitles in Frame" : true
},
"Highlight" : {
"Syntax" : true
},
"Provider" : "libass",
"Time Edit" : {
"Insert Mode" : true
}
},
"Timing" : {
"Default Duration" : 2000
},
"Tool" : {
"Colour Picker" : {
"Mode" : 4,
"RGBAdjust Tool" : false,
"Recent" : "&H000000& &H0000FF& &H00FFFF& &H00FF00& &HFFFF00& &HFF0000& &HFF00FF& &HFFFFFF&"
},
"Fonts Collector" : {
"Action" : 0
},
"Import" : {
"Text" : {
"Actor Separator" : ":",
"Comment Starter" : "#"
}
},
"Kanji Timer" : {
"Interpolation" : true
},
"Paste Lines Over" : {
"Fields" : [
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : false},
{"bool" : true}
]
},
"Preferences" : {
"Page" : 0
},
"Search Replace" : {
"Affect" : 0,
"Field" : 0,
"Match Case" : false,
"RegExp" : false,
"Video Update" : false
},
"Select Lines" : {
"Match" : {
"Case" : false,
"Comment" : false,
"Dialogue" : true
},
"Text" : ""
},
"Select" : {
"Action" : 0,
"Condition" : 0,
"Field" : 0,
"Mode" : 1
},
"Shift Times" : {
"Affect" : 0,
"ByTime" : true,
"Direction" : true,
"Length" : 0,
"Type" : 0
},
"Spell Checker" : {
"Backend" : "hunspell",
"Language" : "en_US"
},
"Style Editor" : {
"Preview Text" : "Aegisub\\N0123 月語"
},
"Thesaurus" : {
"Language" : "en_US"
},
"Timing Post Processor" : {
"Adjacent Bias" : 0.9000000000000000222,
"Enable" : {
"Adjacent" : true,
"Keyframe" : true,
"Lead" : {
"IN" : true,
"OUT" : true
}
},
"Only Selection" : false,
"Threshold" : {
"Adjacent" : 300,
"Key End After" : 6,
"Key End Before" : 5,
"Key Start After" : 4,
"Key Start Before" : 5
}
},
"Tip of the Day" : {
"Current" : 0
},
"Visual" : {
"Always Show": true
}
},
"Version" : {
"Id" : "$Id$",
"Last Version" : 4040,
"Next Check" : 0
},
"Video" : {
"Check Script Res" : 0,
"Default Zoom" : 7,
"Detached" : {
"Enabled" : false,
"Last" : {
"X" : -1,
"Y" : -1
},
"Maximized" : false
},
"Dummy" : {
"FPS" : 23.975999999999999091,
"Last" : {
"Height" : 480,
"Length" : 40000,
"Width" : 640
},
"Pattern" : false
},
"Overscan Mask" : false,
"Provider" : "ffmpegsource",
"Slider" : {
"Fast Jump Step" : 10,
"Show Keyframes" : true
},
"Subtitle Sync" : true,
"Threaded" : false,
"Visual Realtime" : true
}
}

View file

@ -1,5 +1,9 @@
{
"Audio" : [],
"Video" : [],
"Scripts" : []
"Find" : [],
"Keyframes" : [],
"Replace" : [],
"Subtitle" : [],
"Timecodes" : [],
"Video" : []
}

View file

@ -60,11 +60,12 @@
#include "auto4_base.h"
#endif
#include "charset_conv.h"
#include "compat.h"
#include "export_framerate.h"
#include "frame_main.h"
#include "hotkeys.h"
#include "main.h"
#include "options.h"
#include "libresrc/libresrc.h"
#include "plugin_manager.h"
#include "standard_paths.h"
#include "subs_grid.h"
@ -72,6 +73,7 @@
#include "version.h"
#include "video_context.h"
#include <libaegisub/io.h>
///////////////////
// wxWidgets macro
@ -140,6 +142,32 @@ bool AegisubApp::OnInit() {
StartupLog(_T("Inside OnInit"));
frame = NULL;
try {
const std::string conf_mru(StandardPaths::DecodePath(_T("?user/mru.json")));
mru = new agi::MRUManager(conf_mru, GET_DEFAULT_CONFIG(default_mru));
// Set config file
StartupLog(_T("Load configuration"));
try {
const std::string conf_user(StandardPaths::DecodePath(_T("?user/config.json")));
opt = new agi::Options(conf_user, GET_DEFAULT_CONFIG(default_config));
opt->ConfigUser();
/*
#ifdef _DEBUG
const std::string conf_default("default_config.json");
std::istream *stream = agi::io::Open(conf_default);
opt->ConfigDefault(*stream);
delete stream;
#else
opt->ConfigDefault(GET_DEFAULT_CONFIG(default_config));
#endif
*/
// opt->ConfigDefault(GET_DEFAULT_CONFIG(default_config));
} catch (agi::Exception& e) {
wxPrintf("Caught agi::Exception: %s -> %s\n", e.GetName(), e.GetMessage());
}
// Initialize randomizer
StartupLog(_T("Initialize random generator"));
srand(time(NULL));
@ -166,36 +194,9 @@ bool AegisubApp::OnInit() {
wxHandleFatalExceptions(true);
#endif
// Set config file
StartupLog(_T("Load configuration"));
Options.LoadDefaults();
#ifdef __WXMSW__
// Try loading configuration from the install dir if one exists there
if (wxFileName::FileExists(StandardPaths::DecodePath(_T("?data/config.dat")))) {
Options.SetFile(StandardPaths::DecodePath(_T("?data/config.dat")));
Options.Load();
if (Options.AsBool(_T("Local config"))) {
// Local config, make ?user mean ?data so all user settings are placed in install dir
StandardPaths::SetPathValue(_T("?user"), StandardPaths::DecodePath(_T("?data")));
}
else {
// Not local config, we don't want that config.dat file here any more
// It might be a leftover from a really old install
wxRemoveFile(StandardPaths::DecodePath(_T("?data/config.dat")));
}
}
#endif
// TODO: Check if we can write to config.dat and warn the user if we can't
// If we had local config, ?user now means ?data so this will still be loaded from the correct location
Options.SetFile(StandardPaths::DecodePath(_T("?user/config.dat")));
Options.Load();
StartupLog(_T("Store options back"));
Options.SetInt(_T("Last Version"),GetSVNRevision());
Options.LoadDefaults(false,true); // Override options based on version number
Options.Save();
AssTime::UseMSPrecision = Options.AsBool(_T("Use nonstandard Milisecond Times"));
OPT_SET("Version/Last Version")->SetInt(GetSVNRevision());
AssTime::UseMSPrecision = OPT_GET("App/Nonstandard Milisecond Times")->GetBool();
// Set hotkeys file
StartupLog(_T("Load hotkeys"));
@ -205,11 +206,10 @@ bool AegisubApp::OnInit() {
StartupLog(_T("Initialize final locale"));
// Set locale
int lang = Options.AsInt(_T("Locale Code"));
int lang = OPT_GET("App/Locale")->GetInt();
if (lang == -1) {
lang = locale.PickLanguage();
Options.SetInt(_T("Locale Code"),lang);
Options.Save();
OPT_SET("App/Locale")->SetInt(lang);
}
locale.Init(lang);
@ -220,7 +220,7 @@ bool AegisubApp::OnInit() {
// Load Automation scripts
#ifdef WITH_AUTOMATION
StartupLog(_T("Load global Automation scripts"));
global_scripts = new Automation4::AutoloadScriptManager(Options.AsText(_T("Automation Autoload Path")));
global_scripts = new Automation4::AutoloadScriptManager(lagi_wxString(OPT_GET("Path/Automation/Autoload")->GetString()));
#endif
// Load export filters
@ -263,7 +263,8 @@ int AegisubApp::OnExit() {
SubtitleFormat::DestroyFormats();
VideoContext::Clear();
delete plugins;
Options.Clear();
delete opt;
delete mru;
#ifdef WITH_AUTOMATION
delete global_scripts;
#endif
@ -461,7 +462,7 @@ void AegisubApp::MacOpenFile(const wxString &filename) {
if (frame != NULL && !filename.empty()) {
frame->LoadSubtitles(filename);
wxFileName filepath(filename);
Options.SetText(_T("Last open subtitles path"), filepath.GetPath());
OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath()));
}
}
#endif

Some files were not shown because too many files have changed in this diff Show more