Compare commits
62 commits
mia
...
try-travis
Author | SHA1 | Date | |
---|---|---|---|
|
6702556776 | ||
|
bf28e7efc3 | ||
|
c2c44f1ad2 | ||
|
5dd201bc2d | ||
|
3663d118b6 | ||
|
60a722db31 | ||
|
d65643ddee | ||
|
fbca222295 | ||
|
3225ae39f4 | ||
|
888be0607f | ||
|
4200b85fb4 | ||
|
0b8b286767 | ||
|
139132a964 | ||
|
4a3689d6e7 | ||
|
248e69a9b6 | ||
|
46474e0319 | ||
|
50544cf749 | ||
|
e9a68f22b9 | ||
|
d6ddea0f65 | ||
|
2bbed6c5a0 | ||
|
592250eeaa | ||
|
8f40ca44ce | ||
|
f776db2d2b | ||
|
f9ffc46bf6 | ||
|
019e68147e | ||
|
f733297499 | ||
|
4c6d370d51 | ||
|
b7c640d061 | ||
|
2c06f03f5b | ||
|
1819fc8d8b | ||
|
ba54e8d12f | ||
|
c76e410d30 | ||
|
bb2cfb1fcd | ||
|
9abcc03202 | ||
|
837d5a41d7 | ||
|
875456c803 | ||
|
9ddecfdd46 | ||
|
70f27eae4b | ||
|
8d2ef3fca7 | ||
|
48869ae0ad | ||
|
b00285cf71 | ||
|
c6c9e05406 | ||
|
fc1a78aeca | ||
|
38bb1790ab | ||
|
fff08c4650 | ||
|
163d57d6a2 | ||
|
6266867586 | ||
|
4431f678ce | ||
|
419386aadd | ||
|
c4cce28766 | ||
|
1ae2f60b9a | ||
|
b6eebcd7ef | ||
|
bf55264e6d | ||
|
34575a9786 | ||
|
69310d40ae | ||
|
657d9d5149 | ||
|
043a45cf91 | ||
|
ad15c53fb1 | ||
|
841a35a6fd | ||
|
ee7dc6af4e | ||
|
77da2436c5 | ||
|
7be2325629 |
117 changed files with 2199 additions and 1175 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,6 +5,7 @@
|
|||
*.bz2
|
||||
*.cache
|
||||
*.dep
|
||||
*.db
|
||||
*.dll
|
||||
*.dmg
|
||||
*.exe
|
||||
|
@ -14,6 +15,7 @@
|
|||
*.ilk
|
||||
*.log
|
||||
*.manifest
|
||||
!src/dpi_aware.manifest
|
||||
*.mkv
|
||||
*.mo
|
||||
*.ncb
|
||||
|
@ -86,3 +88,4 @@ vendor/luajit/src/lj_vm.s
|
|||
vendor/luajit/src/luajit
|
||||
|
||||
.nuget
|
||||
.vs
|
||||
|
|
84
.travis.yml
84
.travis.yml
|
@ -1,5 +1,5 @@
|
|||
sudo: required
|
||||
dist: trusty
|
||||
dist: bionic
|
||||
language: cpp
|
||||
|
||||
git:
|
||||
|
@ -8,58 +8,62 @@ git:
|
|||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.kitware.com/ubuntu/ xenial main'
|
||||
key_url: 'https://apt.kitware.com/keys/kitware-archive-latest.asc'
|
||||
packages:
|
||||
- libasound2-dev
|
||||
- libfftw3-dev
|
||||
- libhunspell-dev
|
||||
- yasm
|
||||
- libfribidi-dev
|
||||
- libass-dev
|
||||
- libicu-dev
|
||||
- luarocks
|
||||
- g++-5
|
||||
- cmake
|
||||
- build-essential
|
||||
- libboost-all-dev
|
||||
- libffms2-dev
|
||||
- libfontconfig1-dev
|
||||
- libalut-dev
|
||||
- libuchardet-dev
|
||||
- libwxgtk3.0-dev
|
||||
- portaudio19-dev
|
||||
- libpulse-dev
|
||||
- luajit
|
||||
- libluajit-5.1-dev
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: BOOST_VERSION=55
|
||||
- compiler: gcc
|
||||
env: BOOST_VERSION=60
|
||||
before_install:
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5 --slave /usr/bin/gcov gcov /usr/bin/gcov-5
|
||||
env:
|
||||
- {}
|
||||
- BUILD_SUIT=autotools
|
||||
- BUILD_SUIT=autotools CONFIG_FLAGS="--with-system-luajit agi_cv_luajit_is_52=yes"
|
||||
|
||||
install:
|
||||
# Can't install these via the apt addon due to the whitelist
|
||||
- sudo apt-get install -y -qq libffms2-dev libwxgtk3.0-dev libuchardet-dev
|
||||
|
||||
- sudo pip install cpp-coveralls
|
||||
- sudo luarocks install busted > /dev/null
|
||||
- sudo luarocks install moonscript > /dev/null
|
||||
- sudo luarocks install uuid > /dev/null
|
||||
|
||||
- git submodule --quiet init
|
||||
- git submodule --quiet update vendor/googletest
|
||||
|
||||
- cd vendor
|
||||
- rm -rf boost
|
||||
- wget http://sourceforge.net/projects/boost/files/boost/1.${BOOST_VERSION}.0/boost_1_${BOOST_VERSION}_0.tar.bz2/download
|
||||
- tar xjf download
|
||||
- mv boost_1_${BOOST_VERSION}_0 boost
|
||||
- cd boost
|
||||
- ./bootstrap.sh
|
||||
- ./b2 -j3 -layout=system threading=multi cxxflags=-std=c++11 link=shared variant=release --without-python --without-iostreams --without-serialization --without-graph --without-log --without-math --without-signals --without-test --without-wave --without-mpi --without-program_options --without-graph_parallel --without-context --without-coroutine --without-random --without-timer --without-date_time
|
||||
- cd ../..
|
||||
- sudo luarocks install busted > /dev/null
|
||||
- sudo luarocks install moonscript > /dev/null
|
||||
- sudo luarocks install uuid > /dev/null
|
||||
# Remove the CMake provided by travis
|
||||
- sudo rm -rf /usr/local/cmake*
|
||||
- if [ "$BUILD_SUIT" = "autotools" ]; then
|
||||
sudo pip install -U cpp-coveralls;
|
||||
git submodule --quiet init;
|
||||
git submodule --quiet update vendor/googletest;
|
||||
fi
|
||||
|
||||
script:
|
||||
- export CPATH=$(pwd)/vendor/boost
|
||||
- export LD_LIBRARY_PATH=$(pwd)/vendor/boost/stage/lib:$LD_LIBRARY_PATH
|
||||
- export CPPFLAGS="-fprofile-arcs -ftest-coverage"
|
||||
- export LIBS="-lgcov"
|
||||
- autoreconf -if
|
||||
- ./configure BOOST_LDFLAGS="-L$(pwd)/vendor/boost/stage/lib" --enable-debug || cat config.log
|
||||
- make -j3 all test
|
||||
- coveralls --exclude vendor --exclude src --exclude build --exclude tools --exclude libaegisub/windows > /dev/null
|
||||
- if [ "$BUILD_SUIT" = "autotools" ]; then
|
||||
export CPPFLAGS="-fprofile-arcs -ftest-coverage";
|
||||
export LIBS="-lgcov";
|
||||
./autogen.sh;
|
||||
./configure --enable-debug ${CONFIG_FLAGS} || cat config.log;
|
||||
make -j2;
|
||||
make test || travis_terminate 1;
|
||||
coveralls --exclude vendor --exclude src --exclude build --exclude tools --exclude libaegisub/windows > /dev/null;
|
||||
else
|
||||
./build/version.sh .;
|
||||
mkdir build-dir;
|
||||
cd build-dir;
|
||||
cmake -DCMAKE_CXX_FLAGS='-Wall -Wextra -Wno-unused-parameter -pedantic' ..;
|
||||
make -j2;
|
||||
fi
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
|
446
CMakeLists.txt
Normal file
446
CMakeLists.txt
Normal file
|
@ -0,0 +1,446 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
|
||||
project(Aegisub)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
include_directories("build")
|
||||
include_directories("libaegisub/include")
|
||||
|
||||
add_library(libaegisub STATIC
|
||||
libaegisub/common/parser.cpp
|
||||
libaegisub/ass/dialogue_parser.cpp
|
||||
libaegisub/ass/time.cpp
|
||||
libaegisub/ass/uuencode.cpp
|
||||
libaegisub/audio/provider.cpp
|
||||
libaegisub/audio/provider_convert.cpp
|
||||
libaegisub/audio/provider_dummy.cpp
|
||||
libaegisub/audio/provider_hd.cpp
|
||||
libaegisub/audio/provider_lock.cpp
|
||||
libaegisub/audio/provider_pcm.cpp
|
||||
libaegisub/audio/provider_ram.cpp
|
||||
libaegisub/common/cajun/elements.cpp
|
||||
libaegisub/common/cajun/reader.cpp
|
||||
libaegisub/common/cajun/writer.cpp
|
||||
libaegisub/lua/modules/lfs.cpp
|
||||
libaegisub/lua/modules/re.cpp
|
||||
libaegisub/lua/modules/unicode.cpp
|
||||
libaegisub/lua/modules/lpeg.c
|
||||
libaegisub/lua/modules.cpp
|
||||
libaegisub/lua/script_reader.cpp
|
||||
libaegisub/lua/utils.cpp
|
||||
libaegisub/common/calltip_provider.cpp
|
||||
libaegisub/common/character_count.cpp
|
||||
libaegisub/common/charset.cpp
|
||||
libaegisub/common/charset_6937.cpp
|
||||
libaegisub/common/charset_conv.cpp
|
||||
libaegisub/common/color.cpp
|
||||
libaegisub/common/file_mapping.cpp
|
||||
libaegisub/common/format.cpp
|
||||
libaegisub/common/fs.cpp
|
||||
libaegisub/common/hotkey.cpp
|
||||
libaegisub/common/io.cpp
|
||||
libaegisub/common/json.cpp
|
||||
libaegisub/common/kana_table.cpp
|
||||
libaegisub/common/karaoke_matcher.cpp
|
||||
libaegisub/common/keyframe.cpp
|
||||
libaegisub/common/line_iterator.cpp
|
||||
libaegisub/common/log.cpp
|
||||
libaegisub/common/mru.cpp
|
||||
libaegisub/common/option.cpp
|
||||
libaegisub/common/option_value.cpp
|
||||
libaegisub/common/path.cpp
|
||||
libaegisub/common/thesaurus.cpp
|
||||
libaegisub/common/util.cpp
|
||||
libaegisub/common/vfr.cpp
|
||||
libaegisub/common/ycbcr_conv.cpp
|
||||
libaegisub/common/dispatch.cpp
|
||||
)
|
||||
if (UNIX)
|
||||
target_sources(libaegisub PRIVATE
|
||||
libaegisub/unix/access.cpp
|
||||
libaegisub/unix/fs.cpp
|
||||
libaegisub/unix/log.cpp
|
||||
libaegisub/unix/path.cpp
|
||||
libaegisub/unix/util.cpp
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_sources(libaegisub PRIVATE
|
||||
libaegisub/windows/access.cpp
|
||||
libaegisub/windows/charset_conv_win.cpp
|
||||
libaegisub/windows/fs.cpp
|
||||
libaegisub/windows/lagi_pre.cpp
|
||||
libaegisub/windows/log_win.cpp
|
||||
libaegisub/windows/path_win.cpp
|
||||
libaegisub/windows/util_win.cpp
|
||||
)
|
||||
endif(UNIX)
|
||||
SET_TARGET_PROPERTIES(libaegisub PROPERTIES PREFIX "")
|
||||
target_compile_definitions(libaegisub PRIVATE CMAKE_BUILD)
|
||||
|
||||
find_package(LuaJIT REQUIRED)
|
||||
target_include_directories(libaegisub PRIVATE ${LUAJIT_INCLUDE_DIR})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_SOURCE_DIR}/src/libresrc/default_config.cpp ${PROJECT_SOURCE_DIR}/src/libresrc/default_config.h
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/libresrc/default_config_win.json ${PROJECT_SOURCE_DIR}/src/libresrc/default_config_platform.json
|
||||
COMMAND ${LUAJIT_EXECUTABLE} ../../tools/respack.lua manifest.respack default_config.cpp default_config.h
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/libresrc
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_SOURCE_DIR}/src/libresrc/bitmap.cpp ${PROJECT_SOURCE_DIR}/src/libresrc/bitmap.h
|
||||
COMMAND ${LUAJIT_EXECUTABLE} ../../tools/respack.lua manifest.respack ../libresrc/bitmap.cpp ../libresrc/bitmap.h
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/bitmaps
|
||||
)
|
||||
|
||||
add_library(resrc STATIC
|
||||
src/libresrc/bitmap.cpp
|
||||
src/libresrc/default_config.cpp
|
||||
src/libresrc/libresrc.cpp
|
||||
)
|
||||
|
||||
add_library(csri STATIC
|
||||
vendor/csri/lib/list.c
|
||||
vendor/csri/lib/wrap.c
|
||||
vendor/csri/subhelp/logging.c
|
||||
)
|
||||
target_include_directories(csri PRIVATE "vendor/csri/include")
|
||||
IF (WIN32)
|
||||
target_include_directories(csri PRIVATE "vendor/csri/lib/win32")
|
||||
target_sources(csri PRIVATE vendor/csri/lib/win32/enumerate.c)
|
||||
ELSE()
|
||||
target_include_directories(csri PRIVATE "vendor/csri/lib/posix")
|
||||
target_sources(csri PRIVATE vendor/csri/lib/posix/enumerate.c)
|
||||
ENDIF()
|
||||
|
||||
add_executable(Aegisub WIN32
|
||||
src/command/app.cpp
|
||||
src/command/audio.cpp
|
||||
src/command/automation.cpp
|
||||
src/command/command.cpp
|
||||
src/command/edit.cpp
|
||||
src/command/grid.cpp
|
||||
src/command/help.cpp
|
||||
src/command/keyframe.cpp
|
||||
src/command/recent.cpp
|
||||
src/command/subtitle.cpp
|
||||
src/command/time.cpp
|
||||
src/command/timecode.cpp
|
||||
src/command/tool.cpp
|
||||
src/command/video.cpp
|
||||
src/command/vis_tool.cpp
|
||||
src/dialog_about.cpp
|
||||
src/dialog_align.cpp
|
||||
src/dialog_attachments.cpp
|
||||
src/dialog_automation.cpp
|
||||
src/dialog_autosave.cpp
|
||||
src/dialog_colorpicker.cpp
|
||||
src/dialog_detached_video.cpp
|
||||
src/dialog_dummy_video.cpp
|
||||
src/dialog_export.cpp
|
||||
src/dialog_export_ebu3264.cpp
|
||||
src/dialog_fonts_collector.cpp
|
||||
src/dialog_jumpto.cpp
|
||||
src/dialog_kara_timing_copy.cpp
|
||||
src/dialog_log.cpp
|
||||
src/dialog_paste_over.cpp
|
||||
src/dialog_progress.cpp
|
||||
src/dialog_properties.cpp
|
||||
src/dialog_resample.cpp
|
||||
src/dialog_search_replace.cpp
|
||||
src/dialog_selected_choices.cpp
|
||||
src/dialog_selection.cpp
|
||||
src/dialog_shift_times.cpp
|
||||
src/dialog_spellchecker.cpp
|
||||
src/dialog_style_editor.cpp
|
||||
src/dialog_style_manager.cpp
|
||||
src/dialog_styling_assistant.cpp
|
||||
src/dialog_text_import.cpp
|
||||
src/dialog_timing_processor.cpp
|
||||
src/dialog_translation.cpp
|
||||
src/dialog_version_check.cpp
|
||||
src/dialog_video_details.cpp
|
||||
src/dialog_video_properties.cpp
|
||||
src/subtitle_format.cpp
|
||||
src/subtitle_format_ass.cpp
|
||||
src/subtitle_format_ebu3264.cpp
|
||||
src/subtitle_format_encore.cpp
|
||||
src/subtitle_format_microdvd.cpp
|
||||
src/subtitle_format_mkv.cpp
|
||||
src/subtitle_format_srt.cpp
|
||||
src/subtitle_format_ssa.cpp
|
||||
src/subtitle_format_transtation.cpp
|
||||
src/subtitle_format_ttxt.cpp
|
||||
src/subtitle_format_txt.cpp
|
||||
src/visual_tool.cpp
|
||||
src/visual_tool_clip.cpp
|
||||
src/visual_tool_cross.cpp
|
||||
src/visual_tool_drag.cpp
|
||||
src/visual_tool_rotatexy.cpp
|
||||
src/visual_tool_rotatez.cpp
|
||||
src/visual_tool_scale.cpp
|
||||
src/visual_tool_vector_clip.cpp
|
||||
src/MatroskaParser.c
|
||||
src/aegisublocale.cpp
|
||||
src/ass_attachment.cpp
|
||||
src/ass_dialogue.cpp
|
||||
src/ass_entry.cpp
|
||||
src/ass_export_filter.cpp
|
||||
src/ass_exporter.cpp
|
||||
src/ass_file.cpp
|
||||
src/ass_karaoke.cpp
|
||||
src/ass_override.cpp
|
||||
src/ass_parser.cpp
|
||||
src/ass_style.cpp
|
||||
src/ass_style_storage.cpp
|
||||
src/async_video_provider.cpp
|
||||
src/audio_box.cpp
|
||||
src/audio_colorscheme.cpp
|
||||
src/audio_controller.cpp
|
||||
src/audio_display.cpp
|
||||
src/audio_karaoke.cpp
|
||||
src/audio_marker.cpp
|
||||
src/audio_player.cpp
|
||||
src/audio_provider_factory.cpp
|
||||
src/audio_renderer.cpp
|
||||
src/audio_renderer_spectrum.cpp
|
||||
src/audio_renderer_waveform.cpp
|
||||
src/audio_timing_dialogue.cpp
|
||||
src/audio_timing_karaoke.cpp
|
||||
src/auto4_base.cpp
|
||||
src/auto4_lua.cpp
|
||||
src/auto4_lua_assfile.cpp
|
||||
src/auto4_lua_dialog.cpp
|
||||
src/auto4_lua_progresssink.cpp
|
||||
src/base_grid.cpp
|
||||
src/charset_detect.cpp
|
||||
src/colorspace.cpp
|
||||
src/colour_button.cpp
|
||||
src/compat.cpp
|
||||
src/context.cpp
|
||||
src/export_fixstyle.cpp
|
||||
src/export_framerate.cpp
|
||||
src/fft.cpp
|
||||
src/font_file_lister.cpp
|
||||
src/frame_main.cpp
|
||||
src/gl_text.cpp
|
||||
src/gl_wrap.cpp
|
||||
src/grid_column.cpp
|
||||
src/help_button.cpp
|
||||
src/hotkey.cpp
|
||||
src/hotkey_data_view_model.cpp
|
||||
src/image_position_picker.cpp
|
||||
src/initial_line_state.cpp
|
||||
src/main.cpp
|
||||
src/menu.cpp
|
||||
src/mkv_wrap.cpp
|
||||
src/pen.cpp
|
||||
src/persist_location.cpp
|
||||
src/preferences.cpp
|
||||
src/preferences_base.cpp
|
||||
src/project.cpp
|
||||
src/resolution_resampler.cpp
|
||||
src/search_replace_engine.cpp
|
||||
src/selection_controller.cpp
|
||||
src/spellchecker.cpp
|
||||
src/spline.cpp
|
||||
src/spline_curve.cpp
|
||||
src/string_codec.cpp
|
||||
src/subs_controller.cpp
|
||||
src/subs_edit_box.cpp
|
||||
src/subs_edit_ctrl.cpp
|
||||
src/subs_preview.cpp
|
||||
src/subtitles_provider.cpp
|
||||
src/subtitles_provider_libass.cpp
|
||||
src/text_file_reader.cpp
|
||||
src/text_file_writer.cpp
|
||||
src/text_selection_controller.cpp
|
||||
src/thesaurus.cpp
|
||||
src/timeedit_ctrl.cpp
|
||||
src/toggle_bitmap.cpp
|
||||
src/toolbar.cpp
|
||||
src/tooltip_manager.cpp
|
||||
src/utils.cpp
|
||||
src/validators.cpp
|
||||
src/vector2d.cpp
|
||||
src/version.cpp
|
||||
src/video_box.cpp
|
||||
src/video_controller.cpp
|
||||
src/video_display.cpp
|
||||
src/video_frame.cpp
|
||||
src/video_out_gl.cpp
|
||||
src/video_provider_cache.cpp
|
||||
src/video_provider_dummy.cpp
|
||||
src/video_provider_manager.cpp
|
||||
src/video_provider_yuv4mpeg.cpp
|
||||
src/video_slider.cpp
|
||||
src/visual_feature.cpp
|
||||
)
|
||||
target_include_directories(Aegisub PRIVATE ${LUAJIT_INCLUDE_DIR})
|
||||
target_link_libraries(Aegisub ${CMAKE_DL_LIBS} libaegisub ${LUAJIT_LIBRARIES} resrc csri)
|
||||
target_compile_definitions(Aegisub PRIVATE CMAKE_BUILD)
|
||||
|
||||
if (MSVC)
|
||||
set_target_properties(libaegisub PROPERTIES COMPILE_FLAGS "/Yu${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h" COMPILE_FLAGS "/FI${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h")
|
||||
else(MSVC)
|
||||
target_compile_options(libaegisub PRIVATE -include "${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h")
|
||||
endif(MSVC)
|
||||
|
||||
set_property(
|
||||
SOURCE libaegisub/unix/path.cpp
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
P_DATA="${CMAKE_INSTALL_PREFIX}/share/aegisub/"
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
add_definitions("-DNOMINMAX -MP -DINITGUID")
|
||||
set_target_properties(Aegisub PROPERTIES COMPILE_FLAGS "/Yu${PROJECT_SOURCE_DIR}/src/agi_pre.h" COMPILE_FLAGS "/FI${PROJECT_SOURCE_DIR}/src/agi_pre.h")
|
||||
target_link_libraries (Aegisub Usp10)
|
||||
#target_sources(Aegisub PRIVATE src/res/res.rc src/res/strings.rc src/crash_writer_minidump.cpp)
|
||||
target_sources(Aegisub PRIVATE src/res/res.rc src/res/strings.rc src/crash_writer.cpp src/dpi_aware.manifest)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Aegisub)
|
||||
else(MSVC)
|
||||
target_sources(Aegisub PRIVATE src/crash_writer.cpp)
|
||||
target_compile_options(Aegisub PRIVATE -include "${PROJECT_SOURCE_DIR}/src/agi_pre.h")
|
||||
target_link_libraries(Aegisub dl)
|
||||
endif(MSVC)
|
||||
|
||||
if (WIN32)
|
||||
target_sources(Aegisub PRIVATE src/font_file_lister_gdi.cpp)
|
||||
else (WIN32)
|
||||
find_package(Fontconfig REQUIRED)
|
||||
target_link_libraries (Aegisub ${Fontconfig_LIBRARIES})
|
||||
target_sources(Aegisub PRIVATE src/font_file_lister_fontconfig.cpp)
|
||||
set_property(SOURCE src/font_file_lister_fontconfig.cpp PROPERTY INCLUDE_DIRECTORIES "${Fontconfig_INCLUDE_DIRS}")
|
||||
endif (WIN32)
|
||||
|
||||
find_package(ass REQUIRED)
|
||||
include_directories(${ass_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${ass_LIBRARIES})
|
||||
|
||||
find_package(Boost REQUIRED chrono filesystem locale regex system thread)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
target_link_directories(Aegisub PRIVATE ${Boost_LIBRARY_DIRS})
|
||||
target_link_libraries(Aegisub ${Boost_LIBRARIES})
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries (Aegisub ${OPENGL_LIBRARIES})
|
||||
|
||||
find_package(Iconv REQUIRED)
|
||||
include_directories(${Iconv_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${Iconv_LIBRARIES})
|
||||
add_definitions("-DHAVE_ICONV")
|
||||
if (NOT Iconv_IS_BUILT_IN)
|
||||
set_property(
|
||||
SOURCE libaegisub/common/charset_conv.cpp
|
||||
PROPERTY COMPILE_DEFINITIONS AGI_ICONV_CONST
|
||||
)
|
||||
endif (NOT Iconv_IS_BUILT_IN)
|
||||
|
||||
find_package(ICU REQUIRED uc dt in)
|
||||
include_directories(${ICU_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${ICU_LIBRARIES})
|
||||
|
||||
find_package(wxWidgets REQUIRED adv base core gl stc xml)
|
||||
include(${wxWidgets_USE_FILE})
|
||||
target_link_libraries(Aegisub ${wxWidgets_LIBRARIES})
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${ZLIB_LIBRARIES})
|
||||
|
||||
find_package(ALSA)
|
||||
if (ALSA_FOUND)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${ALSA_LIBRARIES})
|
||||
add_definitions("-DWITH_ALSA")
|
||||
target_sources(Aegisub PRIVATE src/audio_player_alsa.cpp)
|
||||
endif(ALSA_FOUND)
|
||||
|
||||
find_package(AviSynth)
|
||||
if (AviSynth_FOUND)
|
||||
target_compile_definitions(Aegisub PRIVATE "WITH_AVISYNTH" "AVS_LINKAGE_DLLIMPORT")
|
||||
target_include_directories(Aegisub PRIVATE ${AviSynth_INCLUDE_DIRS})
|
||||
target_link_libraries(Aegisub Vfw32 ${AviSynth_LIBRARIES})
|
||||
target_sources(Aegisub PRIVATE src/audio_provider_avs.cpp src/avisynth_wrap.cpp src/video_provider_avs.cpp)
|
||||
endif (AviSynth_FOUND)
|
||||
|
||||
target_compile_definitions(Aegisub PRIVATE "WITH_CSRI")
|
||||
target_sources(Aegisub PRIVATE src/subtitles_provider_csri.cpp)
|
||||
set_property(SOURCE src/subtitles_provider_csri.cpp PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/vendor/csri/include")
|
||||
|
||||
if(MSVC)
|
||||
target_link_libraries (Aegisub dsound)
|
||||
add_definitions("-DWITH_DIRECTSOUND")
|
||||
target_sources(Aegisub PRIVATE src/audio_player_dsound.cpp src/audio_player_dsound2.cpp)
|
||||
endif(MSVC)
|
||||
|
||||
find_package(FFMS2)
|
||||
if (FFMS2_FOUND)
|
||||
include_directories(${FFMS2_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${FFMS2_LIBRARIES})
|
||||
add_definitions("-DWITH_FFMS2")
|
||||
target_sources(Aegisub PRIVATE src/audio_provider_ffmpegsource.cpp src/ffmpegsource_common.cpp src/video_provider_ffmpegsource.cpp)
|
||||
endif(FFMS2_FOUND)
|
||||
|
||||
find_package(FFTW)
|
||||
if (FFTW_FOUND)
|
||||
include_directories(${FFTW_INCLUDES})
|
||||
target_link_libraries (Aegisub ${FFTW_LIBRARIES})
|
||||
add_definitions("-DWITH_FFTW3")
|
||||
endif(FFTW_FOUND)
|
||||
|
||||
find_package(Hunspell)
|
||||
if (HUNSPELL_FOUND)
|
||||
include_directories(${HUNSPELL_INCLUDE_DIR})
|
||||
target_link_libraries (Aegisub ${HUNSPELL_LIBRARIES})
|
||||
add_definitions("-DWITH_HUNSPELL")
|
||||
target_sources(Aegisub PRIVATE src/spellchecker_hunspell.cpp)
|
||||
endif (HUNSPELL_FOUND)
|
||||
|
||||
find_package(PulseAudio)
|
||||
if (PULSEAUDIO_FOUND)
|
||||
target_compile_definitions(Aegisub PRIVATE "WITH_LIBPULSE")
|
||||
target_include_directories(Aegisub PRIVATE ${PULSEAUDIO_INCLUDE_DIR})
|
||||
target_link_libraries (Aegisub ${PULSEAUDIO_LIBRARY})
|
||||
target_sources(Aegisub PRIVATE src/audio_player_pulse.cpp)
|
||||
endif(PULSEAUDIO_FOUND)
|
||||
|
||||
find_package(OpenAL)
|
||||
if (OPENAL_FOUND)
|
||||
include_directories(${OPENAL_INCLUDE_DIR})
|
||||
target_link_libraries (Aegisub ${OPENAL_LIBRARY})
|
||||
add_definitions("-DWITH_OPENAL")
|
||||
target_sources(Aegisub PRIVATE src/audio_player_openal.cpp)
|
||||
endif(OPENAL_FOUND)
|
||||
|
||||
#ifdef WITH_OSS
|
||||
#ifdef WITH_PORTAUDIO
|
||||
#ifdef WITH_STARTUPLOG
|
||||
|
||||
find_package(uchardet)
|
||||
if (uchardet_FOUND)
|
||||
include_directories(${uchardet_INCLUDE_DIRS})
|
||||
target_link_libraries (Aegisub ${uchardet_LIBRARIES})
|
||||
add_definitions("-DWITH_UCHARDET")
|
||||
endif(uchardet_FOUND)
|
||||
|
||||
#ifdef WITH_UPDATE_CHECKER
|
||||
|
||||
if (NOT WIN32)
|
||||
set(AEGISUB_COMMAND "aegisub" CACHE STRING "The executable name of Aegisub")
|
||||
set_target_properties(Aegisub PROPERTIES OUTPUT_NAME aegisub)
|
||||
configure_file("packages/desktop/aegisub.desktop.template.cmake.in" "aegisub.desktop" @ONLY)
|
||||
install(FILES "${CMAKE_BINARY_DIR}/aegisub.desktop" DESTINATION "share/applications")
|
||||
install(FILES "packages/desktop/16x16.png" DESTINATION "share/icons/hicolor/16x16/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/22x22.png" DESTINATION "share/icons/hicolor/22x22/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/24x24.png" DESTINATION "share/icons/hicolor/24x24/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/32x32.png" DESTINATION "share/icons/hicolor/32x32/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/48x48.png" DESTINATION "share/icons/hicolor/48x48/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/64x64.png" DESTINATION "share/icons/hicolor/64x64/apps" RENAME aegisub.png)
|
||||
install(FILES "packages/desktop/scalable.svg" DESTINATION "share/icons/hicolor/scalable/apps" RENAME aegisub.svg)
|
||||
endif (NOT WIN32)
|
||||
install (TARGETS Aegisub DESTINATION bin)
|
95
README.md
95
README.md
|
@ -1,85 +1,40 @@
|
|||
[![Build Status](https://travis-ci.org/wangqr/Aegisub.svg?branch=dev)](https://travis-ci.org/wangqr/Aegisub)
|
||||
|
||||
# Aegisub
|
||||
|
||||
For binaries and general information [see the homepage](http://www.aegisub.org).
|
||||
|
||||
The bug tracker can be found at http://devel.aegisub.org.
|
||||
The bug tracker can be found at https://github.com/Aegisub/Aegisub/issues .
|
||||
|
||||
Support is available on [the forums](http://forum.aegisub.org) or [on IRC](irc://irc.rizon.net/aegisub).
|
||||
Support is available on IRC ( irc://irc.rizon.net/aegisub ).
|
||||
|
||||
## Building Aegisub
|
||||
|
||||
### Windows
|
||||
|
||||
Prerequisites:
|
||||
|
||||
1. Visual Studio 2015 (the free Community edition is good enough)
|
||||
2. The June 2010 DirectX SDK (the final release before DirectSound was dropped)
|
||||
3. [Yasm](http://yasm.tortall.net/) installed to somewhere on your path.
|
||||
|
||||
There are a few optional dependencies:
|
||||
|
||||
1. msgfmt, to build the translations
|
||||
2. WinRAR, to build the portable installer
|
||||
3. InnoSetup, to build the regular installer
|
||||
|
||||
All other dependencies are either stored in the repository or are included as submodules.
|
||||
1. CMake 3.14 or later (or you can use an older version by editing the first line in CMakeLists.txt, and download the missing `cmake/FindFontconfig.cmake` from [here](https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/FindFontconfig.cmake)),
|
||||
2. Any compiling toolchain supported by CMake,
|
||||
3. All required dependencies, namely `libass`, `Boost`(with ICU support), `OpenGL`, `libicu`, `wxWidgets`, `zlib`. Additionally, `libiconv` is required on non-POSIX systems. `fontconfig` is required on non-Windows systems.
|
||||
4. Any optional dependencies, namely `ALSA`, `FFMS2`, `FFTW`, `Hunspell`, `OpenAL`, `uchardet`.
|
||||
|
||||
Building:
|
||||
|
||||
1. Clone Aegisub's repository recursively to fetch it and all submodules: `git clone --recursive git@github.com:Aegisub/Aegisub.git` This will take quite a while and requires about 2.5 GB of disk space.
|
||||
2. Open Aegisub.sln
|
||||
3. Build the BuildTasks project.
|
||||
4. Build the entire solution.
|
||||
|
||||
You should now have a `bin` directory in your Aegisub directory which contains `aegisub32d.exe`, along with a pile of other files.
|
||||
|
||||
The Aegisub installer includes some files not built as part of Aegisub (such as Avisynth and VSFilter), so for a fully functional copy of Aegisub you now need to copy all of the files from an installed copy of Aegisub into your `bin` directory (and don't overwrite any of the files already there).
|
||||
You'll also either need to copy the `automation` directory into the `bin` directory, or edit your automation search paths to include the `automation` directory in the source tree.
|
||||
|
||||
After building the solution once, you'll want to switch to the Debug-MinDep configuration, which skips checking if the dependencies are out of date, as that takes a while.
|
||||
|
||||
### OS X
|
||||
|
||||
A vaguely recent version of Xcode and the corresponding command-line tools are required.
|
||||
Nothing older than Xcode 5 has been tested recently, but it is likely that some later versions of Xcode 4 are good enough.
|
||||
|
||||
For personal usage, you can use homebrew to install almost all of Aegisub's dependencies:
|
||||
|
||||
brew install autoconf ffmpeg freetype gettext ffms2 fftw fribidi libass m4
|
||||
brew install --devel --with-gc64 luajit
|
||||
brew install --HEAD icu4c
|
||||
brew link --force icu4c
|
||||
brew link --force gettext
|
||||
brew install --HEAD --c++11 --with-icu4c boost
|
||||
|
||||
wxWidgets is located in vendor/wxWidgets, and can be built like so:
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=1" \
|
||||
./configure --disable-aboutdlg --disable-animatectrl --disable-aui --disable-any \
|
||||
--disable-bannerwindow --disable-base64 --disable-calendar --disable-caret \
|
||||
--disable-cmdline --disable-colourpicker --disable-compat28 --disable-config \
|
||||
--disable-constraints --disable-datepick --disable-dctransform --disable-debugreport \
|
||||
--disable-dialupman --disable-docview --disable-filehistory --disable-finddlg \
|
||||
--disable-fs_archive --disable-fs_inet --disable-fs_zip --disable-fsvolume \
|
||||
--disable-fswatcher --disable-gif --disable-help --disable-html --disable-ipc \
|
||||
--disable-joystick --disable-jpeg --disable-largefile --disable-markup --disable-mdi \
|
||||
--disable-mediactrl --disable-metafiles --disable-miniframe --disable-notifmsg \
|
||||
--disable-numberdlg --disable-pcx --disable-pnm --disable-postscript \
|
||||
--disable-prefseditor --disable-printarch --disable-progressdlg --disable-propgrid \
|
||||
--disable-protocol --disable-protocols --disable-rearrangectrl --disable-ribbon \
|
||||
--disable-richtext --disable-richtooltip --disable-snglinst --disable-sockets \
|
||||
--disable-sockets --disable-sound --disable-splash --disable-splines \
|
||||
--disable-std_iostreams --disable-svg --disable-tarstream --disable-tiff \
|
||||
--disable-tipdlg --disable-tipwindow --disable-url --disable-webkit --disable-webview \
|
||||
--disable-wizarddlg --disable-xrc \
|
||||
--enable-geometry --enable-imaglist --enable-listctrl --enable-stc --with-cocoa \
|
||||
--with-libpng=yes --with-macosx-version-min=10.9 \
|
||||
--with-opengl \
|
||||
--without-libjpeg --without-libtiff --without-regex \
|
||||
&& make
|
||||
|
||||
Once the dependencies are installed, build Aegisub with `autoreconf && ./configure --with-wxdir=/path/to/Aegisub/vendor/wxWidgets && make && make osx-bundle`.
|
||||
`autoreconf` should be skipped if you are building from a source tarball rather than `git`.
|
||||
1. If you decided to build from source:
|
||||
```shell
|
||||
git clone https://github.com/wangqr/Aegisub.git # No --recursive is needed
|
||||
cd Aegisub
|
||||
./build/version.sh . # This will generate build/git_version.h
|
||||
```
|
||||
2. Make an empty directory to hold build outputs:
|
||||
```shell
|
||||
mkdir build-dir
|
||||
```
|
||||
3. Build the project using CMake. Use either cmake-gui, or the command line:
|
||||
```shell
|
||||
cd build-dir
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
## Updating Moonscript
|
||||
|
||||
|
@ -95,4 +50,4 @@ The file is now ready for use, to be placed in `automation/include` within the A
|
|||
## License
|
||||
|
||||
All files in this repository are licensed under various GPL-compatible BSD-style licenses; see LICENCE and the individual source files for more information.
|
||||
The official Windows and OS X builds are GPLv2 due to including fftw3.
|
||||
The official Windows build is GPLv2 due to including fftw3.
|
||||
|
|
|
@ -39,7 +39,7 @@ search = (re, str, start) ->
|
|||
res = regex.search re, str, str\len(), start
|
||||
return unless res != nil
|
||||
first, last = res[0], res[1]
|
||||
ffi.C.free res
|
||||
ffi.gc(res, ffi.C.free)
|
||||
first, last
|
||||
|
||||
replace = (re, replacement, str, max_count) ->
|
||||
|
|
|
@ -40,3 +40,11 @@ Returns: 2 values, all numbers.
|
|||
2. End of the selection, in milliseconds.
|
||||
|
||||
---
|
||||
|
||||
Setting the main frame's status bar text
|
||||
|
||||
function aegisub.set_status_bar_text(text)
|
||||
|
||||
Returns: 0 values
|
||||
|
||||
---
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
<AdditionalLibraryDirectories Condition="'$(Platform)'=='Win32'">$(DXSDK_DIR)\Lib\x86</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories Condition="'$(Platform)'=='x64'">$(DXSDK_DIR)\Lib\x64</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Update git_version.h -->
|
||||
|
|
19
cmake/FindAviSynth.cmake
Normal file
19
cmake/FindAviSynth.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_AviSynth QUIET AviSynth)
|
||||
find_path(AviSynth_INCLUDE_DIRS
|
||||
NAMES avisynth.h
|
||||
PATHS ${PC_AviSynth_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(AviSynth_LIBRARIES
|
||||
NAMES avisynth
|
||||
PATHS ${PC_AviSynth_LIBRARY_DIRS}
|
||||
)
|
||||
set(AviSynth_VERSION ${PC_AviSynth_VERSION})
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(AviSynth
|
||||
FOUND_VAR AviSynth_FOUND
|
||||
REQUIRED_VARS
|
||||
AviSynth_LIBRARIES
|
||||
AviSynth_INCLUDE_DIRS
|
||||
VERSION_VAR AviSynth_VERSION
|
||||
)
|
19
cmake/FindFFMS2.cmake
Normal file
19
cmake/FindFFMS2.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_FFMS2 QUIET ffms2)
|
||||
find_path(FFMS2_INCLUDE_DIRS
|
||||
NAMES ffms.h ffmscompat.h
|
||||
PATHS ${PC_FFMS2_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(FFMS2_LIBRARIES
|
||||
NAMES ffms2
|
||||
PATHS ${PC_FFMS2_LIBRARY_DIRS}
|
||||
)
|
||||
set(FFMS2_VERSION ${PC_FFMS2_VERSION})
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FFMS2
|
||||
FOUND_VAR FFMS2_FOUND
|
||||
REQUIRED_VARS
|
||||
FFMS2_LIBRARIES
|
||||
FFMS2_INCLUDE_DIRS
|
||||
VERSION_VAR FFMS2_VERSION
|
||||
)
|
119
cmake/FindFFTW.cmake
Normal file
119
cmake/FindFFTW.cmake
Normal file
|
@ -0,0 +1,119 @@
|
|||
# - Find the FFTW library
|
||||
#
|
||||
# Usage:
|
||||
# find_package(FFTW [REQUIRED] [QUIET] )
|
||||
#
|
||||
# It sets the following variables:
|
||||
# FFTW_FOUND ... true if fftw is found on the system
|
||||
# FFTW_LIBRARIES ... full path to fftw library
|
||||
# FFTW_INCLUDES ... fftw include directory
|
||||
#
|
||||
# The following variables will be checked by the function
|
||||
# FFTW_USE_STATIC_LIBS ... if true, only static libraries are found
|
||||
# FFTW_ROOT ... if set, the libraries are exclusively searched
|
||||
# under this path
|
||||
# FFTW_LIBRARY ... fftw library to use
|
||||
# FFTW_INCLUDE_DIR ... fftw include directory
|
||||
#
|
||||
|
||||
#If environment variable FFTWDIR is specified, it has same effect as FFTW_ROOT
|
||||
if( NOT FFTW_ROOT AND ENV{FFTWDIR} )
|
||||
set( FFTW_ROOT $ENV{FFTWDIR} )
|
||||
endif()
|
||||
|
||||
# Check if we can use PkgConfig
|
||||
find_package(PkgConfig)
|
||||
|
||||
#Determine from PKG
|
||||
if( PKG_CONFIG_FOUND AND NOT FFTW_ROOT )
|
||||
pkg_check_modules( PKG_FFTW QUIET "fftw3" )
|
||||
endif()
|
||||
|
||||
#Check whether to search static or dynamic libs
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES} )
|
||||
|
||||
if( ${FFTW_USE_STATIC_LIBS} )
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} )
|
||||
else()
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX} )
|
||||
endif()
|
||||
|
||||
if( FFTW_ROOT )
|
||||
|
||||
#find libs
|
||||
find_library(
|
||||
FFTW_LIB
|
||||
NAMES "fftw3"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_library(
|
||||
FFTWF_LIB
|
||||
NAMES "fftw3f"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_library(
|
||||
FFTWL_LIB
|
||||
NAMES "fftw3l"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
#find includes
|
||||
find_path(
|
||||
FFTW_INCLUDES
|
||||
NAMES "fftw3.h"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "include"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
else()
|
||||
|
||||
find_library(
|
||||
FFTW_LIB
|
||||
NAMES "fftw3"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
|
||||
find_library(
|
||||
FFTWF_LIB
|
||||
NAMES "fftw3f"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
|
||||
|
||||
find_library(
|
||||
FFTWL_LIB
|
||||
NAMES "fftw3l"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
|
||||
find_path(
|
||||
FFTW_INCLUDES
|
||||
NAMES "fftw3.h"
|
||||
PATHS ${PKG_FFTW_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
|
||||
endif( FFTW_ROOT )
|
||||
|
||||
set(FFTW_LIBRARIES ${FFTW_LIB} ${FFTWF_LIB})
|
||||
|
||||
if(FFTWL_LIB)
|
||||
set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTWL_LIB})
|
||||
endif()
|
||||
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} )
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FFTW DEFAULT_MSG
|
||||
FFTW_INCLUDES FFTW_LIBRARIES)
|
||||
|
||||
mark_as_advanced(FFTW_INCLUDES FFTW_LIBRARIES FFTW_LIB FFTWF_LIB FFTWL_LIB)
|
||||
|
57
cmake/FindHunspell.cmake
Normal file
57
cmake/FindHunspell.cmake
Normal file
|
@ -0,0 +1,57 @@
|
|||
# - Try to find Hunspell
|
||||
# Once done this will define
|
||||
#
|
||||
# HUNSPELL_FOUND - system has Hunspell
|
||||
# HUNSPELL_INCLUDE_DIR - the Hunspell include directory
|
||||
# HUNSPELL_LIBRARIES - Link these to use Hunspell
|
||||
#
|
||||
# Redistribution and use of this file is allowed according to the terms of the
|
||||
# MIT license. For details see the file COPYING-CMAKE-MODULES.
|
||||
|
||||
|
||||
if ( HUNSPELL_INCLUDE_DIR AND HUNSPELL_LIBRARIES )
|
||||
# in cache already
|
||||
SET(Hunspell_FIND_QUIETLY TRUE)
|
||||
endif ( HUNSPELL_INCLUDE_DIR AND HUNSPELL_LIBRARIES )
|
||||
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
if( NOT WIN32 )
|
||||
find_package(PkgConfig)
|
||||
|
||||
pkg_check_modules(HUNSPELL_PKG QUIET hunspell)
|
||||
endif( NOT WIN32 )
|
||||
|
||||
FIND_PATH(HUNSPELL_INCLUDE_DIR NAMES hunspell.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
HINTS
|
||||
${HUNSPELL_PKG_INCLUDE_DIRS} # Generated by pkg-config
|
||||
PATH_SUFFIXES hunspell
|
||||
)
|
||||
|
||||
FIND_LIBRARY(HUNSPELL_LIBRARIES NAMES hunspell-1.7 hunspell-1.6 hunspell-1.5 hunspell-1.4 hunspell-1.3 hunspell-1.2 hunspell ${HUNSPELL_PKG_LIBRARIES}
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
HINTS
|
||||
${HUNSPELL_PKG_LIBRARY_DIRS} # Generated by pkg-config
|
||||
PATH_SUFFIXES
|
||||
lib64
|
||||
lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Hunspell DEFAULT_MSG HUNSPELL_LIBRARIES HUNSPELL_INCLUDE_DIR )
|
||||
|
||||
# show the HUNSPELL_INCLUDE_DIR and HUNSPELL_LIBRARIES variables only in the advanced view
|
||||
MARK_AS_ADVANCED(HUNSPELL_INCLUDE_DIR HUNSPELL_LIBRARIES )
|
||||
|
||||
add_library(hunspell UNKNOWN IMPORTED)
|
||||
set_target_properties(hunspell PROPERTIES IMPORTED_LOCATION ${HUNSPELL_LIBRARIES} INTERFACE_INCLUDE_DIRECTORIES ${HUNSPELL_INCLUDE_DIR})
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
# At least statically compiled hunspell 1.7.0 requires HUNSPELL_STATIC
|
||||
# For other versions, it should not hurt
|
||||
set_target_properties(hunspell PROPERTIES INTERFACE_COMPILE_DEFINITIONS HUNSPELL_STATIC)
|
||||
endif ()
|
215
cmake/FindLuaJIT.cmake
Normal file
215
cmake/FindLuaJIT.cmake
Normal file
|
@ -0,0 +1,215 @@
|
|||
#.rst:
|
||||
# FindLuaJIT
|
||||
# ----------
|
||||
#
|
||||
#
|
||||
#
|
||||
# Locate Lua library This module defines
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# LUAJIT_FOUND - if false, do not try to link to Lua
|
||||
# LUAJIT_EXECUTABLE - path to luajit command
|
||||
# LUAJIT_LIBRARIES - both lua and lualib
|
||||
# LUAJIT_LIBRARY_DIR - list of dir(s) that contain the libraries to link
|
||||
# LUAJIT_INCLUDE_DIR - where to find lua.h
|
||||
# LUAJIT_LINK_FLAGS - Link flags that are required, platform dependant
|
||||
# LUAJIT_VERSION_STRING - the version of Lua found
|
||||
# LUAJIT_VERSION_MAJOR - the major version of Lua
|
||||
# LUAJIT_VERSION_MINOR - the minor version of Lua
|
||||
# LUAJIT_VERSION_PATCH - the patch version of Lua
|
||||
#
|
||||
#
|
||||
#
|
||||
# Note that the expected include convention is
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# #include "lua.h"
|
||||
#
|
||||
# and not
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# #include <lua/lua.h>
|
||||
#
|
||||
# This is because, the lua location is not standardized and may exist in
|
||||
# locations other than lua/
|
||||
|
||||
unset(_lua_include_subdirs)
|
||||
unset(_lua_library_names)
|
||||
|
||||
# this is a function only to have all the variables inside go away automatically
|
||||
function(set_lua_version_vars)
|
||||
set(LUA_VERSIONS5 5.3 5.2 5.1 5.0)
|
||||
set(LUAJIT_VERSIONS 2.0)
|
||||
|
||||
if (LuaJIT_FIND_VERSION_EXACT)
|
||||
if (LuaJIT_FIND_VERSION_COUNT GREATER 1)
|
||||
set(luajit_append_versions ${LuaJIT_FIND_VERSION_MAJOR}.${LuaJIT_FIND_VERSION_MINOR})
|
||||
endif ()
|
||||
elseif (LuaJIT_FIND_VERSION)
|
||||
# once there is a different major version supported this should become a loop
|
||||
if (NOT LuaJIT_FIND_VERSION_MAJOR GREATER 5)
|
||||
if (LuaJIT_FIND_VERSION_COUNT EQUAL 1)
|
||||
set(luajit_append_versions ${LUA_VERSIONS5})
|
||||
else ()
|
||||
foreach (subver IN LISTS LUA_VERSIONS5)
|
||||
if (NOT subver VERSION_LESS ${LuaJIT_FIND_VERSION})
|
||||
list(APPEND luajit_append_versions ${subver})
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
endif ()
|
||||
else ()
|
||||
# once there is a different major version supported this should become a loop
|
||||
set(luajit_append_versions ${LUA_VERSIONS5})
|
||||
endif ()
|
||||
|
||||
foreach (ver IN LISTS luajit_append_versions LUAJIT_VERSIONS)
|
||||
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}")
|
||||
list(APPEND _luajit_include_subdirs
|
||||
include/luajit${CMAKE_MATCH_1}${CMAKE_MATCH_2}
|
||||
include/luajit${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
include/luajit-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
)
|
||||
|
||||
list(APPEND _luajit_library_names
|
||||
luajit${CMAKE_MATCH_1}${CMAKE_MATCH_2}
|
||||
luajit${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
luajit.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
luajit-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
)
|
||||
endforeach ()
|
||||
|
||||
foreach (ver IN LISTS LUA_VERSIONS5)
|
||||
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}")
|
||||
list(APPEND _luajit_library_names
|
||||
luajit${CMAKE_MATCH_1}${CMAKE_MATCH_2}
|
||||
luajit${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
luajit.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
luajit-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
)
|
||||
endforeach ()
|
||||
|
||||
set(_luajit_include_subdirs "${_luajit_include_subdirs}" PARENT_SCOPE)
|
||||
set(_luajit_library_names "${_luajit_library_names}" PARENT_SCOPE)
|
||||
endfunction(set_lua_version_vars)
|
||||
|
||||
set_lua_version_vars()
|
||||
|
||||
find_path(LUAJIT_INCLUDE_DIR luajit.h
|
||||
HINTS
|
||||
ENV LUAJIT_DIR
|
||||
PATH_SUFFIXES ${_luajit_include_subdirs} include/luajit-2.1 include/luajit include
|
||||
PATHS
|
||||
${LUAJIT_DIR}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
)
|
||||
unset(_luajit_include_subdirs)
|
||||
|
||||
find_library(LUAJIT_LIBRARY
|
||||
NAMES ${_luajit_library_names} luajit
|
||||
HINTS
|
||||
ENV LUAJIT_DIR
|
||||
PATH_SUFFIXES lib
|
||||
PATHS
|
||||
${LUAJIT_DIR}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
unset(_luajit_library_names)
|
||||
|
||||
if (LUAJIT_LIBRARY)
|
||||
# include the math library for Unix
|
||||
if (UNIX AND NOT APPLE AND NOT BEOS)
|
||||
find_library(LUAJIT_MATH_LIBRARY m)
|
||||
set(LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}")
|
||||
# For Windows and Mac, don't need to explicitly include the math library
|
||||
else ()
|
||||
set(LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}")
|
||||
endif ()
|
||||
|
||||
set(LUAJIT_LIBRARY_DIR )
|
||||
foreach (lib ${LUAJIT_LIBRARIES})
|
||||
get_filename_component(lib_dir ${lib} DIRECTORY CACHE)
|
||||
list(APPEND LUAJIT_LIBRARY_DIR ${lib_dir})
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
||||
# This macro is taken word-for-word from the FindLua module and placed into a macro to keep the semantics the same
|
||||
macro(get_lua_versions include_dir)
|
||||
# At least 5.[012] have different ways to express the version
|
||||
# so all of them need to be tested. Lua 5.2 defines LUA_VERSION
|
||||
# and LUA_RELEASE as joined by the C preprocessor, so avoid those.
|
||||
file(STRINGS "${${include_dir}}/lua.h" lua_version_strings
|
||||
REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*")
|
||||
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUAJIT_LUA_VERSION_MAJOR ";${lua_version_strings};")
|
||||
if (LUAJIT_LUA_VERSION_MAJOR MATCHES "^[0-9]+$")
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUAJIT_LUA_VERSION_MINOR ";${lua_version_strings};")
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUAJIT_LUA_VERSION_PATCH ";${lua_version_strings};")
|
||||
set(LUA_VERSION_STRING "${LUAJIT_LUA_VERSION_MAJOR}.${LUAJIT_LUA_VERSION_MINOR}.${LUAJIT_LUA_VERSION_PATCH}")
|
||||
else ()
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUAJIT_LUA_VERSION_STRING ";${lua_version_strings};")
|
||||
if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$")
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUAJIT_LUA_VERSION_STRING ";${lua_version_strings};")
|
||||
endif ()
|
||||
string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUAJIT_LUA_VERSION_MAJOR "${LUAJIT_LUA_VERSION_STRING}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUAJIT_LUA_VERSION_MINOR "${LUAJIT_LUA_VERSION_STRING}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUAJIT_LUA_VERSION_PATCH "${LUAJIT_LUA_VERSION_STRING}")
|
||||
endif ()
|
||||
|
||||
unset(lua_version_strings)
|
||||
endmacro(get_lua_versions)
|
||||
|
||||
if (LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/luajit.h")
|
||||
# LuaJIT defines two preprocessor macros:
|
||||
# LUA_VERSION -> version string with lua version in it
|
||||
# LUA_VERSION_NUM -> numeric representation, i.e. 20003 for 2.0.3
|
||||
# This just parses the LUAJIT_VERSION macro and extracts the version.
|
||||
file(STRINGS "${LUAJIT_INCLUDE_DIR}/luajit.h" version_strings
|
||||
REGEX "^#define[ \t]+LUAJIT_VERSION?[ \t]+(\"LuaJIT [0-9\\.]+(-(beta|alpha)[0-9]*)?\").*")
|
||||
|
||||
string(REGEX REPLACE ".*;#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([0-9\\.]+(-(beta|alpha)[0-9]*)?)\"[ \t]*;.*" "\\1" LUAJIT_VERSION_STRING_SHORT ";${version_strings};")
|
||||
string(REGEX REPLACE ".*;([0-9]+\\.[0-9]+\\.[0-9]+(-(beta|alpha)[0-9]*)?);.*" "\\1" luajit_version_num ";${LUAJIT_VERSION_STRING_SHORT};")
|
||||
|
||||
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.(-(beta|alpha)[0-9]*)?$" "\\1" LUAJIT_VERSION_MAJOR "${luajit_version_num}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9](-(beta|alpha)[0-9]*)?$" "\\1" LUAJIT_VERSION_MINOR "${luajit_version_num}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+(-(beta|alpha)[0-9]*)?)$" "\\1" LUAJIT_VERSION_PATCH "${luajit_version_num}")
|
||||
|
||||
get_lua_versions(LUAJIT_INCLUDE_DIR)
|
||||
|
||||
set(LUAJIT_VERSION_STRING "${LUAJIT_LUA_VERSION_STRING} (${LUAJIT_VERSION_STRING_SHORT})")
|
||||
|
||||
message("Found LuaJIT ${LUAJIT_VERSION_STRING}")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# Not sure why this is true, but its mentioned here:
|
||||
# http://luajit.org/install.html#embed
|
||||
set(LUAJIT_LINK_FLAGS "-pagezero_size 10000 -image_base 100000000")
|
||||
else()
|
||||
set(LUAJIT_LINK_FLAGS "")
|
||||
endif()
|
||||
|
||||
find_program(LUAJIT_EXECUTABLE luajit)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LuaJIT_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT
|
||||
FOUND_VAR LuaJIT_FOUND
|
||||
REQUIRED_VARS LUAJIT_EXECUTABLE LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR
|
||||
VERSION_VAR LUAJIT_VERSION_STRING)
|
||||
|
||||
mark_as_advanced(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY LUAJIT_LIBRARY_DIR LUAJIT_LINK_FLAGS)
|
71
cmake/FindPulseAudio.cmake
Normal file
71
cmake/FindPulseAudio.cmake
Normal file
|
@ -0,0 +1,71 @@
|
|||
# Try to find the PulseAudio library
|
||||
#
|
||||
# Once done this will define:
|
||||
#
|
||||
# PULSEAUDIO_FOUND - system has the PulseAudio library
|
||||
# PULSEAUDIO_INCLUDE_DIR - the PulseAudio include directory
|
||||
# PULSEAUDIO_LIBRARY - the libraries needed to use PulseAudio
|
||||
# PULSEAUDIO_MAINLOOP_LIBRARY - the libraries needed to use PulsAudio Mainloop
|
||||
#
|
||||
# The minimum required version of PulseAudio can be specified using the
|
||||
# standard syntax, e.g. find_package(PulseAudio 1.0)
|
||||
|
||||
# Copyright (c) 2008, Matthias Kretz, <kretz@kde.org>
|
||||
# Copyright (c) 2009, Marcus Hufgard, <Marcus.Hufgard@hufgard.de>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
# Support PULSEAUDIO_MINIMUM_VERSION for compatibility:
|
||||
if(NOT PulseAudio_FIND_VERSION)
|
||||
set(PulseAudio_FIND_VERSION "${PULSEAUDIO_MINIMUM_VERSION}")
|
||||
endif(NOT PulseAudio_FIND_VERSION)
|
||||
|
||||
# the minimum version of PulseAudio we require
|
||||
if(NOT PulseAudio_FIND_VERSION)
|
||||
set(PulseAudio_FIND_VERSION "0.9.9")
|
||||
endif(NOT PulseAudio_FIND_VERSION)
|
||||
|
||||
if (NOT WIN32)
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(PC_PULSEAUDIO QUIET libpulse>=${PulseAudio_FIND_VERSION})
|
||||
pkg_check_modules(PC_PULSEAUDIO_MAINLOOP QUIET libpulse-mainloop-glib)
|
||||
endif (NOT WIN32)
|
||||
|
||||
find_path(PULSEAUDIO_INCLUDE_DIR pulse/pulseaudio.h
|
||||
HINTS
|
||||
${PC_PULSEAUDIO_INCLUDEDIR}
|
||||
${PC_PULSEAUDIO_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(PULSEAUDIO_LIBRARY NAMES pulse libpulse
|
||||
HINTS
|
||||
${PC_PULSEAUDIO_LIBDIR}
|
||||
${PC_PULSEAUDIO_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_library(PULSEAUDIO_MAINLOOP_LIBRARY NAMES pulse-mainloop pulse-mainloop-glib libpulse-mainloop-glib
|
||||
HINTS
|
||||
${PC_PULSEAUDIO_LIBDIR}
|
||||
${PC_PULSEAUDIO_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
# Store the version number in the cache, so we don't have to search every time again:
|
||||
if (PULSEAUDIO_INCLUDE_DIR AND NOT PULSEAUDIO_VERSION)
|
||||
|
||||
# get PulseAudio's version from its version.h, and compare it with our minimum version
|
||||
file(STRINGS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h" pulse_version_h
|
||||
REGEX ".*pa_get_headers_version\\(\\).*"
|
||||
)
|
||||
string(REGEX REPLACE ".*pa_get_headers_version\\(\\)\ \\(\"([0-9]+\\.[0-9]+\\.[0-9]+)[^\"]*\"\\).*" "\\1"
|
||||
_PULSEAUDIO_VERSION "${pulse_version_h}")
|
||||
|
||||
set(PULSEAUDIO_VERSION "${_PULSEAUDIO_VERSION}" CACHE STRING "Version number of PulseAudio" FORCE)
|
||||
endif (PULSEAUDIO_INCLUDE_DIR AND NOT PULSEAUDIO_VERSION)
|
||||
|
||||
# Use the new extended syntax of find_package_handle_standard_args(), which also handles version checking:
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PulseAudio REQUIRED_VARS PULSEAUDIO_LIBRARY PULSEAUDIO_INCLUDE_DIR
|
||||
VERSION_VAR PULSEAUDIO_VERSION )
|
||||
|
||||
mark_as_advanced(PULSEAUDIO_INCLUDE_DIR PULSEAUDIO_LIBRARY PULSEAUDIO_MAINLOOP_LIBRARY)
|
19
cmake/Findass.cmake
Normal file
19
cmake/Findass.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_ass QUIET ass)
|
||||
find_path(ass_INCLUDE_DIRS
|
||||
NAMES ass/ass.h ass/ass_types.h
|
||||
PATHS ${PC_ass_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(ass_LIBRARIES
|
||||
NAMES ass
|
||||
PATHS ${PC_ass_LIBRARY_DIRS}
|
||||
)
|
||||
set(ass_VERSION ${PC_ass_VERSION})
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ass
|
||||
FOUND_VAR ass_FOUND
|
||||
REQUIRED_VARS
|
||||
ass_LIBRARIES
|
||||
ass_INCLUDE_DIRS
|
||||
VERSION_VAR ass_VERSION
|
||||
)
|
19
cmake/Finduchardet.cmake
Normal file
19
cmake/Finduchardet.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_uchardet QUIET uchardet)
|
||||
find_path(uchardet_INCLUDE_DIRS
|
||||
NAMES uchardet/uchardet.h
|
||||
PATHS ${PC_uchardet_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(uchardet_LIBRARIES
|
||||
NAMES uchardet
|
||||
PATHS ${PC_uchardet_LIBRARY_DIRS}
|
||||
)
|
||||
set(uchardet_VERSION ${PC_uchardet_VERSION})
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(uchardet
|
||||
FOUND_VAR uchardet_FOUND
|
||||
REQUIRED_VARS
|
||||
uchardet_LIBRARIES
|
||||
uchardet_INCLUDE_DIRS
|
||||
VERSION_VAR uchardet_VERSION
|
||||
)
|
|
@ -24,7 +24,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace agi {
|
||||
Time::Time(int time) : time(util::mid(0, time, 10 * 60 * 60 * 1000 - 1)) { }
|
||||
Time::Time(int time) : time(util::mid(0, time, 10 * 60 * 60 * 1000 - 6)) { }
|
||||
|
||||
Time::Time(std::string const& text) {
|
||||
int after_decimal = -1;
|
||||
|
@ -56,29 +56,39 @@ Time::Time(std::string const& text) {
|
|||
time = (time * 60 + current) * 1000;
|
||||
|
||||
// Limit to the valid range
|
||||
time = util::mid(0, time, 10 * 60 * 60 * 1000 - 1);
|
||||
time = util::mid(0, time, 10 * 60 * 60 * 1000 - 6);
|
||||
}
|
||||
|
||||
std::string Time::GetAssFormatted(bool msPrecision) const {
|
||||
int ass_time = msPrecision ? time : int(*this);
|
||||
std::string ret(10 + msPrecision, ':');
|
||||
ret[0] = '0' + GetTimeHours();
|
||||
ret[2] = '0' + (time % (60 * 60 * 1000)) / (60 * 1000 * 10);
|
||||
ret[3] = '0' + (time % (10 * 60 * 1000)) / (60 * 1000);
|
||||
ret[5] = '0' + (time % (60 * 1000)) / (1000 * 10);
|
||||
ret[6] = '0' + (time % (10 * 1000)) / 1000;
|
||||
ret[0] = '0' + ass_time / 3600000;
|
||||
ret[2] = '0' + (ass_time % (60 * 60 * 1000)) / (60 * 1000 * 10);
|
||||
ret[3] = '0' + (ass_time % (10 * 60 * 1000)) / (60 * 1000);
|
||||
ret[5] = '0' + (ass_time % (60 * 1000)) / (1000 * 10);
|
||||
ret[6] = '0' + (ass_time % (10 * 1000)) / 1000;
|
||||
ret[7] = '.';
|
||||
ret[8] = '0' + (time % 1000) / 100;
|
||||
ret[9] = '0' + (time % 100) / 10;
|
||||
ret[8] = '0' + (ass_time % 1000) / 100;
|
||||
ret[9] = '0' + (ass_time % 100) / 10;
|
||||
if (msPrecision)
|
||||
ret[10] = '0' + time % 10;
|
||||
ret[10] = '0' + ass_time % 10;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Time::GetTimeHours() const { return time / 3600000; }
|
||||
int Time::GetTimeMinutes() const { return (time % 3600000) / 60000; }
|
||||
int Time::GetTimeSeconds() const { return (time % 60000) / 1000; }
|
||||
int Time::GetTimeMiliseconds() const { return (time % 1000); }
|
||||
int Time::GetTimeCentiseconds() const { return (time % 1000) / 10; }
|
||||
std::string Time::GetSrtFormatted() const {
|
||||
std::string ret(12, ':');
|
||||
ret[0] = '0';
|
||||
ret[1] = '0' + time / 3600000;
|
||||
ret[3] = '0' + (time % (60 * 60 * 1000)) / (60 * 1000 * 10);
|
||||
ret[4] = '0' + (time % (10 * 60 * 1000)) / (60 * 1000);
|
||||
ret[6] = '0' + (time % (60 * 1000)) / (1000 * 10);
|
||||
ret[7] = '0' + (time % (10 * 1000)) / 1000;
|
||||
ret[8] = ',';
|
||||
ret[9] = '0' + (time % 1000) / 100;
|
||||
ret[10] = '0' + (time % 100) / 10;
|
||||
ret[11] = '0' + time % 10;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SmpteFormatter::SmpteFormatter(vfr::Framerate fps, char sep)
|
||||
: fps(std::move(fps))
|
||||
|
|
|
@ -41,14 +41,14 @@ public:
|
|||
|
||||
void FillBuffer(void *buf, int64_t start, int64_t count64) const override {
|
||||
auto count = static_cast<size_t>(count64);
|
||||
assert(count == count64);
|
||||
assert(count64 >= 0 && count == static_cast<uint64_t>(count64));
|
||||
|
||||
src_buf.resize(count * src_bytes_per_sample * channels);
|
||||
source->GetAudio(src_buf.data(), start, count);
|
||||
|
||||
auto dest = static_cast<int16_t*>(buf);
|
||||
|
||||
for (int64_t i = 0; i < count * channels; ++i) {
|
||||
for (size_t i = 0; i < count * channels; ++i) {
|
||||
int64_t sample = 0;
|
||||
|
||||
// 8 bits per sample is assumed to be unsigned with a bias of 127,
|
||||
|
@ -85,7 +85,7 @@ public:
|
|||
|
||||
void FillBuffer(void *buf, int64_t start, int64_t count64) const override {
|
||||
auto count = static_cast<size_t>(count64);
|
||||
assert(count == count64);
|
||||
assert(count64 >= 0 && count == static_cast<uint64_t>(count64));
|
||||
|
||||
src_buf.resize(count * channels);
|
||||
source->GetAudio(&src_buf[0], start, count);
|
||||
|
@ -119,7 +119,7 @@ public:
|
|||
|
||||
void FillBuffer(void *buf, int64_t start, int64_t count64) const override {
|
||||
auto count = static_cast<size_t>(count64);
|
||||
assert(count == count64);
|
||||
assert(count64 >= 0 && count == static_cast<uint64_t>(count64));
|
||||
|
||||
src_buf.resize(count * src_channels);
|
||||
source->GetAudio(&src_buf[0], start, count);
|
||||
|
|
|
@ -31,6 +31,8 @@ struct utext_deleter {
|
|||
};
|
||||
using utext_ptr = std::unique_ptr<UText, utext_deleter>;
|
||||
|
||||
UChar32 ass_special_chars[] = {'n', 'N', 'h'};
|
||||
|
||||
icu::BreakIterator& get_break_iterator(const char *ptr, size_t len) {
|
||||
static std::unique_ptr<icu::BreakIterator> bi;
|
||||
static std::once_flag token;
|
||||
|
@ -65,10 +67,25 @@ size_t count_in_range(Iterator begin, Iterator end, int mask) {
|
|||
UChar32 c;
|
||||
int i = 0;
|
||||
U8_NEXT_UNSAFE(begin + pos, i, c);
|
||||
if ((U_GET_GC_MASK(c) & mask) == 0)
|
||||
++count;
|
||||
if ((U_GET_GC_MASK(c) & mask) == 0) {
|
||||
if (mask & U_GC_Z_MASK && pos != 0) {
|
||||
UChar32 *result = std::find(std::begin(ass_special_chars), std::end(ass_special_chars), c);
|
||||
if (result != std::end(ass_special_chars)) {
|
||||
UChar32 c2;
|
||||
i = 0;
|
||||
U8_PREV_UNSAFE(begin + pos, i, c2);
|
||||
if (c2 != (UChar32) '\\')
|
||||
++count;
|
||||
else if (!(mask & U_GC_P_MASK))
|
||||
--count;
|
||||
}
|
||||
else
|
||||
++count;
|
||||
}
|
||||
else
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -29,37 +29,44 @@ namespace agi { namespace charset {
|
|||
std::string Detect(agi::fs::path const& file) {
|
||||
agi::read_file_mapping fp(file);
|
||||
|
||||
// FIXME: It is an empty file. Treat as ascii
|
||||
if (fp.size() == 0) return "ascii";
|
||||
|
||||
// FIXME: Dirty hack for Matroska. These 4 bytes are the magic
|
||||
// number of EBML which is used by mkv and webm
|
||||
if (fp.size() >= 4) {
|
||||
const char* buf = fp.read(0, 4);
|
||||
if (!strncmp(buf, "\x1a\x45\xdf\xa3", 4))
|
||||
return "binary";
|
||||
}
|
||||
|
||||
#ifdef WITH_UCHARDET
|
||||
agi::scoped_holder<uchardet_t> ud(uchardet_new(), uchardet_delete);
|
||||
for (uint64_t offset = 0; offset < fp.size(); ) {
|
||||
auto read = std::min<uint64_t>(65536, fp.size() - offset);
|
||||
auto buf = fp.read(offset, read);
|
||||
uchardet_handle_data(ud, buf, read);
|
||||
offset += read;
|
||||
}
|
||||
uchardet_data_end(ud);
|
||||
std::string encoding = uchardet_get_charset(ud);
|
||||
return encoding.empty() ? "binary" : encoding;
|
||||
#else
|
||||
|
||||
// Look for utf-8 BOM
|
||||
if (fp.size() >= 3) {
|
||||
const char* buf = fp.read(0, 3);
|
||||
if (!strncmp(buf, "\xef\xbb\xbf", 3))
|
||||
return "utf-8";
|
||||
}
|
||||
|
||||
// If it's over 100 MB it's either binary or big enough that we won't
|
||||
// be able to do anything useful with it anyway
|
||||
if (fp.size() > 100 * 1024 * 1024)
|
||||
return "binary";
|
||||
|
||||
uint64_t binaryish = 0;
|
||||
|
||||
#ifdef WITH_UCHARDET
|
||||
agi::scoped_holder<uchardet_t> ud(uchardet_new(), uchardet_delete);
|
||||
for (uint64_t offset = 0; offset < fp.size(); ) {
|
||||
auto read = std::min<uint64_t>(4096, fp.size() - offset);
|
||||
auto buf = fp.read(offset, read);
|
||||
uchardet_handle_data(ud, buf, read);
|
||||
uchardet_data_end(ud);
|
||||
if (*uchardet_get_charset(ud))
|
||||
return uchardet_get_charset(ud);
|
||||
|
||||
offset += read;
|
||||
|
||||
// A dumb heuristic to detect binary files
|
||||
for (size_t i = 0; i < read; ++i) {
|
||||
if ((unsigned char)buf[i] < 32 && (buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t'))
|
||||
++binaryish;
|
||||
}
|
||||
|
||||
if (binaryish > offset / 8)
|
||||
return "binary";
|
||||
}
|
||||
return uchardet_get_charset(ud);
|
||||
#else
|
||||
auto read = std::min<uint64_t>(4096, fp.size());
|
||||
auto read = std::min<uint64_t>(65536, fp.size());
|
||||
auto buf = fp.read(0, read);
|
||||
for (size_t i = 0; i < read; ++i) {
|
||||
if ((unsigned char)buf[i] < 32 && (buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t'))
|
||||
|
|
|
@ -366,7 +366,7 @@ size_t IconvWrapper::RequiredBufferSize(std::string const& str) {
|
|||
}
|
||||
|
||||
size_t IconvWrapper::RequiredBufferSize(const char* src, size_t srcLen) {
|
||||
char buff[512];
|
||||
char buff[65536];
|
||||
size_t charsWritten = 0;
|
||||
size_t res;
|
||||
|
||||
|
|
|
@ -28,16 +28,14 @@ public:
|
|||
Time(std::string const& text);
|
||||
|
||||
/// Get millisecond, rounded to centisecond precision
|
||||
operator int() const { return time / 10 * 10; }
|
||||
|
||||
int GetTimeHours() const; ///< Get the hours portion of this time
|
||||
int GetTimeMinutes() const; ///< Get the minutes portion of this time
|
||||
int GetTimeSeconds() const; ///< Get the seconds portion of this time
|
||||
int GetTimeMiliseconds() const; ///< Get the miliseconds portion of this time
|
||||
int GetTimeCentiseconds() const; ///< Get the centiseconds portion of this time
|
||||
// Always round up for 5ms because the range is [start, stop)
|
||||
operator int() const { return (time + 5) - (time + 5) % 10; }
|
||||
|
||||
/// Return the time as a string
|
||||
/// @param ms Use milliseconds precision, for non-ASS formats
|
||||
std::string GetAssFormatted(bool ms=false) const;
|
||||
|
||||
/// Return the time as a string
|
||||
std::string GetSrtFormatted() const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace agi {
|
|||
DEFINE_FS_EXCEPTION(FileNotFound, FileNotAccessible, "File not found: ");
|
||||
|
||||
/// An error of some unknown type has occured
|
||||
DEFINE_EXCEPTION(FileSystemUnknownError, FileSystemError);;
|
||||
DEFINE_EXCEPTION(FileSystemUnknownError, FileSystemError);
|
||||
|
||||
/// The path exists, but isn't a file
|
||||
DEFINE_FS_EXCEPTION(NotAFile, FileNotAccessible, "Path is not a file (and should be): ");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifdef __cplusplus
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) && !defined(CMAKE_BUILD)
|
||||
#include "../acconf.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libaegisub/lua/ffi.h"
|
||||
#include "libaegisub/lua/utils.h"
|
||||
|
||||
extern "C" int luaopen_luabins(lua_State *L);
|
||||
// extern "C" int luaopen_luabins(lua_State *L);
|
||||
extern "C" int luaopen_re_impl(lua_State *L);
|
||||
extern "C" int luaopen_unicode_impl(lua_State *L);
|
||||
extern "C" int luaopen_lfs_impl(lua_State *L);
|
||||
|
@ -38,7 +38,7 @@ void preload_modules(lua_State *L) {
|
|||
set_field(L, "aegisub.__unicode_impl", luaopen_unicode_impl);
|
||||
set_field(L, "aegisub.__lfs_impl", luaopen_lfs_impl);
|
||||
set_field(L, "lpeg", luaopen_lpeg);
|
||||
set_field(L, "luabins", luaopen_luabins);
|
||||
// set_field(L, "luabins", luaopen_luabins);
|
||||
|
||||
lua_pop(L, 2);
|
||||
|
||||
|
|
|
@ -2334,7 +2334,7 @@ static int matchl (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
static struct luaL_reg pattreg[] = {
|
||||
static struct luaL_Reg pattreg[] = {
|
||||
{"match", matchl},
|
||||
{"print", printpat_l},
|
||||
{"locale", locale_l},
|
||||
|
@ -2360,7 +2360,7 @@ static struct luaL_reg pattreg[] = {
|
|||
};
|
||||
|
||||
|
||||
static struct luaL_reg metapattreg[] = {
|
||||
static struct luaL_Reg metapattreg[] = {
|
||||
{"__add", union_l},
|
||||
{"__pow", star_l},
|
||||
{"__sub", diff_l},
|
||||
|
|
13
packages/desktop/aegisub.desktop.template.cmake.in
Normal file
13
packages/desktop/aegisub.desktop.template.cmake.in
Normal file
|
@ -0,0 +1,13 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=Aegisub
|
||||
GenericName=Subtitle Editor
|
||||
Comment=Create and edit subtitles for film and videos.
|
||||
Exec=env GDK_BACKEND=x11 @AEGISUB_COMMAND@ %f
|
||||
TryExec=@AEGISUB_COMMAND@
|
||||
Icon=aegisub
|
||||
Terminal=false
|
||||
Categories=AudioVideo;AudioVideoEditing;
|
||||
MimeType=application/x-srt;text/plain;text/x-ass;text/x-microdvd;text/x-ssa;
|
||||
StartupNotify=true
|
|
@ -4,7 +4,7 @@ Type=Application
|
|||
_Name=Aegisub
|
||||
_GenericName=Subtitle Editor
|
||||
_Comment=Create and edit subtitles for film and videos.
|
||||
Exec=@AEGISUB_COMMAND@ %f
|
||||
Exec=env GDK_BACKEND=x11 @AEGISUB_COMMAND@ %f
|
||||
TryExec=@AEGISUB_COMMAND@
|
||||
Icon=aegisub
|
||||
Terminal=false
|
||||
|
|
|
@ -66,6 +66,7 @@ src_OBJ := \
|
|||
$(d)help_button.o \
|
||||
$(d)hotkey.o \
|
||||
$(d)hotkey_data_view_model.o \
|
||||
$(d)image_position_picker.o \
|
||||
$(d)initial_line_state.o \
|
||||
$(d)main.o \
|
||||
$(d)menu.o \
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) && !defined(CMAKE_BUILD)
|
||||
#include "../acconf.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class AssStyle final : public AssEntry, public AssEntryListHook {
|
|||
public:
|
||||
std::string name = "Default"; ///< Name of the style; must be case-insensitively unique within a file despite being case-sensitive
|
||||
std::string font = "Arial"; ///< Font face name
|
||||
double fontsize = 20.; ///< Font size
|
||||
double fontsize = 48.; ///< Font size
|
||||
|
||||
agi::Color primary{ 255, 255, 255 }; ///< Default text color
|
||||
agi::Color secondary{ 255, 0, 0 }; ///< Text color for not-yet-reached karaoke syllables
|
||||
|
|
|
@ -129,10 +129,9 @@ END_EVENT_TABLE()
|
|||
void AudioBox::OnMouseWheel(wxMouseEvent &evt) {
|
||||
if (!ForwardMouseWheelEvent(audioDisplay, evt))
|
||||
return;
|
||||
|
||||
bool zoom = evt.CmdDown() != OPT_GET("Audio/Wheel Default to Zoom")->GetBool();
|
||||
if (!zoom) {
|
||||
int amount = -evt.GetWheelRotation() * GetClientSize().GetWidth() / (evt.GetWheelDelta() * 3);
|
||||
int amount = -evt.GetWheelRotation();
|
||||
// If the user did a horizontal scroll the amount should be inverted
|
||||
// for it to be natural.
|
||||
if (evt.GetWheelAxis() == 1) amount = -amount;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
AudioColorScheme::AudioColorScheme(int prec, std::string const& scheme_name, int audio_rendering_style)
|
||||
: palette((3<<prec) + 3)
|
||||
, factor(1<<prec)
|
||||
, factor((size_t)1<<prec)
|
||||
{
|
||||
std::string opt_base = "Colour/Schemes/" + scheme_name + "/";
|
||||
switch (static_cast<AudioRenderingStyle>(audio_rendering_style))
|
||||
|
|
|
@ -128,8 +128,9 @@ public:
|
|||
/// Get the current Selection colour
|
||||
wxColour Selection() const { return focused ? sel_focused_colour : sel_colour; }
|
||||
};
|
||||
}
|
||||
|
||||
class AudioDisplayScrollbar final : public AudioDisplayInteractionObject {
|
||||
class AudioDisplay::AudioDisplayScrollbar final : public AudioDisplayInteractionObject {
|
||||
static const int height = 15;
|
||||
static const int min_width = 10;
|
||||
|
||||
|
@ -267,9 +268,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
const int AudioDisplayScrollbar::min_width;
|
||||
const int AudioDisplay::AudioDisplayScrollbar::min_width;
|
||||
|
||||
class AudioDisplayTimeline final : public AudioDisplayInteractionObject {
|
||||
class AudioDisplay::AudioDisplayTimeline final : public AudioDisplayInteractionObject {
|
||||
int duration = 0; ///< Total duration in ms
|
||||
double ms_per_pixel = 1.0; ///< Milliseconds per pixel
|
||||
int pixel_left = 0; ///< Leftmost visible pixel (i.e. scroll position)
|
||||
|
@ -478,6 +479,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
class AudioStyleRangeMerger final : public AudioRenderingStyleRanges {
|
||||
typedef std::map<int, AudioRenderingStyle> style_map;
|
||||
public:
|
||||
|
|
|
@ -47,11 +47,6 @@ class AudioRenderer;
|
|||
class AudioRendererBitmapProvider;
|
||||
class TimeRange;
|
||||
|
||||
// Helper classes used in implementation of the audio display
|
||||
namespace {
|
||||
class AudioDisplayScrollbar;
|
||||
class AudioDisplayTimeline;
|
||||
}
|
||||
class AudioDisplayInteractionObject;
|
||||
class AudioMarkerInteractionObject;
|
||||
|
||||
|
@ -79,9 +74,11 @@ class AudioDisplay: public wxWindow {
|
|||
agi::AudioProvider *provider = nullptr;
|
||||
|
||||
/// Scrollbar helper object
|
||||
class AudioDisplayScrollbar;
|
||||
std::unique_ptr<AudioDisplayScrollbar> scrollbar;
|
||||
|
||||
/// Timeline helper object
|
||||
class AudioDisplayTimeline;
|
||||
std::unique_ptr<AudioDisplayTimeline> timeline;
|
||||
|
||||
/// The interaction object for the last-dragged audio marker
|
||||
|
|
|
@ -280,8 +280,7 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
|
|||
split_area->Refresh(false);
|
||||
scroll_timer.Start(50);
|
||||
split_area->CaptureMouse();
|
||||
wxTimerEvent evt;
|
||||
OnScrollTimer(evt);
|
||||
OnScrollTimer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -317,7 +316,7 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
|
|||
split_area->Refresh(false);
|
||||
}
|
||||
|
||||
void AudioKaraoke::OnScrollTimer(wxTimerEvent &) {
|
||||
void AudioKaraoke::OnScrollTimer() {
|
||||
scroll_x += scroll_dir * char_width * 3;
|
||||
|
||||
int max_scroll = rendered_line.GetWidth() + 20 - split_area->GetClientSize().GetWidth();
|
||||
|
@ -329,6 +328,10 @@ void AudioKaraoke::OnScrollTimer(wxTimerEvent &) {
|
|||
split_area->Refresh(false);
|
||||
}
|
||||
|
||||
void AudioKaraoke::OnScrollTimer(wxTimerEvent&) {
|
||||
OnScrollTimer();
|
||||
}
|
||||
|
||||
void AudioKaraoke::LoadFromLine() {
|
||||
scroll_x = 0;
|
||||
scroll_timer.Stop();
|
||||
|
|
|
@ -142,7 +142,8 @@ class AudioKaraoke final : public wxWindow {
|
|||
void OnPaint(wxPaintEvent &event);
|
||||
void OnSize(wxSizeEvent &event);
|
||||
void OnAudioOpened(agi::AudioProvider *provider);
|
||||
void OnScrollTimer(wxTimerEvent &event);
|
||||
void OnScrollTimer();
|
||||
void OnScrollTimer(wxTimerEvent& event);
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
#include <cguid.h>
|
||||
|
||||
namespace {
|
||||
class DirectSoundPlayer;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <mmsystem.h>
|
||||
#include <process.h>
|
||||
#include <dsound.h>
|
||||
#include <cguid.h>
|
||||
|
||||
namespace {
|
||||
class DirectSoundPlayer2Thread;
|
||||
|
|
|
@ -144,7 +144,7 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
|||
// update access time of index file so it won't get cleaned away
|
||||
agi::fs::Touch(CacheName);
|
||||
|
||||
AudioSource = FFMS_CreateAudioSource(filename.string().c_str(), TrackNumber, Index, -1, &ErrInfo);
|
||||
AudioSource = FFMS_CreateAudioSource(filename.string().c_str(), TrackNumber, Index, FFMS_DELAY_FIRST_VIDEO_TRACK, &ErrInfo);
|
||||
if (!AudioSource)
|
||||
throw agi::AudioProviderError(std::string("Failed to open audio track: ") + ErrInfo.Buffer);
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ void AudioSpectrumRenderer::RecreateCache()
|
|||
|
||||
if (provider)
|
||||
{
|
||||
size_t block_count = (size_t)((provider->GetNumSamples() + (size_t)(1<<derivation_dist) - 1) >> derivation_dist);
|
||||
size_t block_count = (size_t)((provider->GetNumSamples() + ((size_t)1<<derivation_dist) - 1) >> derivation_dist);
|
||||
cache = agi::make_unique<AudioSpectrumCache>(block_count, this);
|
||||
|
||||
#ifdef WITH_FFTW3
|
||||
|
@ -170,7 +170,7 @@ void AudioSpectrumRenderer::FillBlock(size_t block_index, float *block)
|
|||
assert(cache);
|
||||
assert(block);
|
||||
|
||||
int64_t first_sample = ((int64_t)block_index) << derivation_dist;
|
||||
int64_t first_sample = (((int64_t)block_index) << derivation_dist) - ((int64_t)1 << derivation_size);
|
||||
provider->GetAudio(&audio_scratch[0], first_sample, 2 << derivation_size);
|
||||
|
||||
#ifdef WITH_FFTW3
|
||||
|
@ -181,7 +181,7 @@ void AudioSpectrumRenderer::FillBlock(size_t block_index, float *block)
|
|||
double scale_factor = 9 / sqrt(2 << (derivation_size + 1));
|
||||
|
||||
fftw_complex *o = dft_output;
|
||||
for (size_t si = 1<<derivation_size; si > 0; --si)
|
||||
for (size_t si = (size_t)1<<derivation_size; si > 0; --si)
|
||||
{
|
||||
*block++ = log10( sqrt(o[0][0] * o[0][0] + o[0][1] * o[0][1]) * scale_factor + 1 );
|
||||
o++;
|
||||
|
|
|
@ -390,7 +390,7 @@ int AudioTimingControllerKaraoke::MoveMarker(KaraokeMarker *marker, int new_posi
|
|||
void AudioTimingControllerKaraoke::AnnounceChanges(int syl) {
|
||||
if (syl < 0) return;
|
||||
|
||||
if (syl == cur_syl || syl == cur_syl + 1) {
|
||||
if (static_cast<unsigned>(syl) == cur_syl || static_cast<unsigned>(syl) == cur_syl + 1) {
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "audio_timing.h"
|
||||
#include "command/command.h"
|
||||
#include "compat.h"
|
||||
#include "frame_main.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "options.h"
|
||||
#include "project.h"
|
||||
|
@ -52,6 +53,7 @@
|
|||
#include "video_controller.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <libaegisub/dispatch.h>
|
||||
#include <libaegisub/format.h>
|
||||
#include <libaegisub/lua/ffi.h>
|
||||
#include <libaegisub/lua/modules.h>
|
||||
|
@ -270,6 +272,19 @@ namespace {
|
|||
return 2;
|
||||
}
|
||||
|
||||
int lua_set_status_text(lua_State *L)
|
||||
{
|
||||
const agi::Context *c = get_context(L);
|
||||
if (!c || !c->frame) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
std::string text = check_string(L, 1);
|
||||
lua_pop(L, 1);
|
||||
agi::dispatch::Main().Async([=] { c->frame->StatusTimeout(to_wx(text)); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int project_properties(lua_State *L)
|
||||
{
|
||||
const agi::Context *c = get_context(L);
|
||||
|
@ -473,6 +488,7 @@ namespace {
|
|||
set_field<get_translation>(L, "gettext");
|
||||
set_field<project_properties>(L, "project_properties");
|
||||
set_field<lua_get_audio_selection>(L, "get_audio_selection");
|
||||
set_field<lua_set_status_text>(L, "set_status_text");
|
||||
|
||||
// store aegisub table to globals
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
|
|
|
@ -744,8 +744,8 @@ namespace Automation4 {
|
|||
, can_modify(can_modify)
|
||||
, can_set_undo(can_set_undo)
|
||||
{
|
||||
for (auto& line : ass->Info)
|
||||
lines.push_back(nullptr);
|
||||
// for (auto& line : ass->Info) lines.push_back(nullptr);
|
||||
lines.insert(lines.end(), ass->Info.size(), nullptr);
|
||||
for (auto& line : ass->Styles)
|
||||
lines.push_back(&line);
|
||||
for (auto& line : ass->Events)
|
||||
|
|
751
src/avisynth.h
751
src/avisynth.h
|
@ -1,751 +0,0 @@
|
|||
// Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
|
||||
// http://www.avisynth.org
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
|
||||
// http://www.gnu.org/copyleft/gpl.html .
|
||||
//
|
||||
// Linking Avisynth statically or dynamically with other modules is making a
|
||||
// combined work based on Avisynth. Thus, the terms and conditions of the GNU
|
||||
// General Public License cover the whole combination.
|
||||
//
|
||||
// As a special exception, the copyright holders of Avisynth give you
|
||||
// permission to link Avisynth with independent modules that communicate with
|
||||
// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
|
||||
// terms of these independent modules, and to copy and distribute the
|
||||
// resulting combined work under terms of your choice, provided that
|
||||
// every copy of the combined work is accompanied by a complete copy of
|
||||
// the source code of Avisynth (the version of Avisynth used to produce the
|
||||
// combined work), being distributed under the terms of the GNU General
|
||||
// Public License plus this exception. An independent module is a module
|
||||
// which is not derived from or based on Avisynth, such as 3rd-party filters,
|
||||
// import and export plugins, or graphical user interfaces.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __AVISYNTH_H__
|
||||
#define __AVISYNTH_H__
|
||||
|
||||
enum { AVISYNTH_INTERFACE_VERSION = 3 };
|
||||
|
||||
|
||||
/* Define all types necessary for interfacing with avisynth.dll
|
||||
Moved from internal.h */
|
||||
|
||||
// Win32 API macros, notably the types BYTE, DWORD, ULONG, etc.
|
||||
#include <windef.h>
|
||||
|
||||
// COM interface macros
|
||||
#include <objbase.h>
|
||||
|
||||
|
||||
// Raster types used by VirtualDub & Avisynth
|
||||
#define in64 (__int64)(unsigned short)
|
||||
typedef unsigned long Pixel; // this will break on 64-bit machines!
|
||||
typedef unsigned long Pixel32;
|
||||
typedef unsigned char Pixel8;
|
||||
typedef long PixCoord;
|
||||
typedef long PixDim;
|
||||
typedef long PixOffset;
|
||||
|
||||
|
||||
/* Compiler-specific crap */
|
||||
|
||||
// Tell MSVC to stop precompiling here
|
||||
#ifdef _MSC_VER
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// Set up debugging macros for MS compilers; for others, step down to the
|
||||
// standard <assert.h> interface
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#define _RPT0(a,b) ((void)0)
|
||||
#define _RPT1(a,b,c) ((void)0)
|
||||
#define _RPT2(a,b,c,d) ((void)0)
|
||||
#define _RPT3(a,b,c,d,e) ((void)0)
|
||||
#define _RPT4(a,b,c,d,e,f) ((void)0)
|
||||
|
||||
#define _ASSERTE(x) assert(x)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// I had problems with Premiere wanting 1-byte alignment for its structures,
|
||||
// so I now set the Avisynth struct alignment explicitly here.
|
||||
#pragma pack(push,8)
|
||||
|
||||
#define FRAME_ALIGN 16
|
||||
// Default frame alignment is 16 bytes, to help P4, when using SSE2
|
||||
|
||||
// The VideoInfo struct holds global information about a clip (i.e.
|
||||
// information that does not depend on the frame number). The GetVideoInfo
|
||||
// method in IClip returns this struct.
|
||||
|
||||
// Audio Sample information
|
||||
typedef float SFLOAT;
|
||||
|
||||
enum {SAMPLE_INT8 = 1<<0,
|
||||
SAMPLE_INT16 = 1<<1,
|
||||
SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware.
|
||||
SAMPLE_INT32 = 1<<3,
|
||||
SAMPLE_FLOAT = 1<<4};
|
||||
|
||||
enum {
|
||||
PLANAR_Y=1<<0,
|
||||
PLANAR_U=1<<1,
|
||||
PLANAR_V=1<<2,
|
||||
PLANAR_ALIGNED=1<<3,
|
||||
PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED,
|
||||
PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED,
|
||||
PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED,
|
||||
};
|
||||
|
||||
struct VideoInfo {
|
||||
int width, height; // width=0 means no video
|
||||
unsigned fps_numerator, fps_denominator;
|
||||
int num_frames;
|
||||
// This is more extensible than previous versions. More properties can be added seeminglesly.
|
||||
|
||||
// Colorspace properties.
|
||||
enum {
|
||||
CS_BGR = 1<<28,
|
||||
CS_YUV = 1<<29,
|
||||
CS_INTERLEAVED = 1<<30,
|
||||
CS_PLANAR = 1<<31
|
||||
};
|
||||
|
||||
// Specific colorformats
|
||||
enum { CS_UNKNOWN = 0,
|
||||
CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED,
|
||||
CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED,
|
||||
CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED,
|
||||
CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, planar
|
||||
CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, planar
|
||||
CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR // same as above
|
||||
};
|
||||
int pixel_type; // changed to int as of 2.5
|
||||
|
||||
|
||||
int audio_samples_per_second; // 0 means no audio
|
||||
int sample_type; // as of 2.5
|
||||
__int64 num_audio_samples; // changed as of 2.5
|
||||
int nchannels; // as of 2.5
|
||||
|
||||
// Imagetype properties
|
||||
|
||||
int image_type;
|
||||
|
||||
enum {
|
||||
IT_BFF = 1<<0,
|
||||
IT_TFF = 1<<1,
|
||||
IT_FIELDBASED = 1<<2
|
||||
};
|
||||
|
||||
// useful functions of the above
|
||||
bool HasVideo() const { return (width!=0); }
|
||||
bool HasAudio() const { return (audio_samples_per_second!=0); }
|
||||
bool IsRGB() const { return !!(pixel_type&CS_BGR); }
|
||||
bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties
|
||||
bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; }
|
||||
bool IsYUV() const { return !!(pixel_type&CS_YUV ); }
|
||||
bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; }
|
||||
bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); }
|
||||
bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); }
|
||||
bool Is(int property) const { return ((pixel_type & property)==property ); }
|
||||
bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); }
|
||||
bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
|
||||
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); }
|
||||
bool IsBFF() const { return !!(image_type & IT_BFF); }
|
||||
bool IsTFF() const { return !!(image_type & IT_TFF); }
|
||||
|
||||
bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this
|
||||
int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes
|
||||
int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images
|
||||
int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); }
|
||||
__int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; }
|
||||
int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; }
|
||||
__int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; }
|
||||
__int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); }
|
||||
int AudioChannels() const { return nchannels; }
|
||||
int SampleType() const{ return sample_type;}
|
||||
bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);}
|
||||
int SamplesPerSecond() const { return audio_samples_per_second; }
|
||||
int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();}
|
||||
void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; }
|
||||
void Set(int property) { image_type|=property; }
|
||||
void Clear(int property) { image_type&=~property; }
|
||||
|
||||
int BitsPerPixel() const {
|
||||
switch (pixel_type) {
|
||||
case CS_BGR24:
|
||||
return 24;
|
||||
case CS_BGR32:
|
||||
return 32;
|
||||
case CS_YUY2:
|
||||
return 16;
|
||||
case CS_YV12:
|
||||
case CS_I420:
|
||||
return 12;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int BytesPerChannelSample() const {
|
||||
switch (sample_type) {
|
||||
case SAMPLE_INT8:
|
||||
return sizeof(signed char);
|
||||
case SAMPLE_INT16:
|
||||
return sizeof(signed short);
|
||||
case SAMPLE_INT24:
|
||||
return 3;
|
||||
case SAMPLE_INT32:
|
||||
return sizeof(signed int);
|
||||
case SAMPLE_FLOAT:
|
||||
return sizeof(SFLOAT);
|
||||
default:
|
||||
_ASSERTE("Sample type not recognized!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// useful mutator
|
||||
void SetFPS(unsigned numerator, unsigned denominator) {
|
||||
if ((numerator == 0) || (denominator == 0)) {
|
||||
fps_numerator = 0;
|
||||
fps_denominator = 1;
|
||||
}
|
||||
else {
|
||||
unsigned x=numerator, y=denominator;
|
||||
while (y) { // find gcd
|
||||
unsigned t = x%y; x = y; y = t;
|
||||
}
|
||||
fps_numerator = numerator/x;
|
||||
fps_denominator = denominator/x;
|
||||
}
|
||||
}
|
||||
|
||||
// Range protected multiply-divide of FPS
|
||||
void MulDivFPS(unsigned multiplier, unsigned divisor) {
|
||||
unsigned __int64 numerator = UInt32x32To64(fps_numerator, multiplier);
|
||||
unsigned __int64 denominator = UInt32x32To64(fps_denominator, divisor);
|
||||
|
||||
unsigned __int64 x=numerator, y=denominator;
|
||||
while (y) { // find gcd
|
||||
unsigned __int64 t = x%y; x = y; y = t;
|
||||
}
|
||||
numerator /= x; // normalize
|
||||
denominator /= x;
|
||||
|
||||
unsigned __int64 temp = numerator | denominator; // Just looking top bit
|
||||
unsigned u = 0;
|
||||
while (temp & 0xffffffff80000000) { // or perhaps > 16777216*2
|
||||
temp = Int64ShrlMod32(temp, 1);
|
||||
u++;
|
||||
}
|
||||
if (u) { // Scale to fit
|
||||
const unsigned round = 1 << (u-1);
|
||||
SetFPS( (unsigned)Int64ShrlMod32(numerator + round, u),
|
||||
(unsigned)Int64ShrlMod32(denominator + round, u) );
|
||||
}
|
||||
else {
|
||||
fps_numerator = (unsigned)numerator;
|
||||
fps_denominator = (unsigned)denominator;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for same colorspace
|
||||
bool IsSameColorspace(const VideoInfo& vi) const {
|
||||
if (vi.pixel_type == pixel_type) return TRUE;
|
||||
if (IsYV12() && vi.IsYV12()) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// VideoFrameBuffer holds information about a memory block which is used
|
||||
// for video data. For efficiency, instances of this class are not deleted
|
||||
// when the refcount reaches zero; instead they're stored in a linked list
|
||||
// to be reused. The instances are deleted when the corresponding AVS
|
||||
// file is closed.
|
||||
|
||||
class VideoFrameBuffer {
|
||||
BYTE* const data;
|
||||
const int data_size;
|
||||
// sequence_number is incremented every time the buffer is changed, so
|
||||
// that stale views can tell they're no longer valid.
|
||||
long sequence_number;
|
||||
|
||||
friend class VideoFrame;
|
||||
friend class Cache;
|
||||
friend class ScriptEnvironment;
|
||||
long refcount;
|
||||
|
||||
public:
|
||||
VideoFrameBuffer(int size);
|
||||
VideoFrameBuffer();
|
||||
~VideoFrameBuffer();
|
||||
|
||||
const BYTE* GetReadPtr() const { return data; }
|
||||
BYTE* GetWritePtr() { ++sequence_number; return data; }
|
||||
int GetDataSize() { return data_size; }
|
||||
int GetSequenceNumber() { return sequence_number; }
|
||||
int GetRefcount() { return refcount; }
|
||||
};
|
||||
|
||||
|
||||
class IClip;
|
||||
class PClip;
|
||||
class PVideoFrame;
|
||||
class IScriptEnvironment;
|
||||
class AVSValue;
|
||||
|
||||
|
||||
// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new
|
||||
// is overloaded to recycle class instances.
|
||||
|
||||
class VideoFrame {
|
||||
int refcount;
|
||||
VideoFrameBuffer* const vfb;
|
||||
const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture.
|
||||
|
||||
friend class PVideoFrame;
|
||||
void AddRef() { InterlockedIncrement((long *)&refcount); }
|
||||
void Release() { if (refcount==1) InterlockedDecrement(&vfb->refcount); InterlockedDecrement((long *)&refcount); }
|
||||
|
||||
friend class ScriptEnvironment;
|
||||
friend class Cache;
|
||||
|
||||
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height);
|
||||
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV);
|
||||
|
||||
void* operator new(size_t size);
|
||||
// TESTME: OFFSET U/V may be switched to what could be expected from AVI standard!
|
||||
public:
|
||||
int GetPitch() const { return pitch; }
|
||||
int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; }
|
||||
int GetRowSize() const { return row_size; }
|
||||
int GetRowSize(int plane) const {
|
||||
switch (plane) {
|
||||
case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0;
|
||||
case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED:
|
||||
if (pitchUV) {
|
||||
int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize
|
||||
if (r<=pitchUV)
|
||||
return r;
|
||||
return row_size>>1;
|
||||
} else return 0;
|
||||
case PLANAR_Y_ALIGNED:
|
||||
int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize
|
||||
if (r<=pitch)
|
||||
return r;
|
||||
return row_size;
|
||||
}
|
||||
return row_size; }
|
||||
int GetHeight() const { return height; }
|
||||
int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; }
|
||||
|
||||
// generally you shouldn't use these three
|
||||
VideoFrameBuffer* GetFrameBuffer() const { return vfb; }
|
||||
int GetOffset() const { return offset; }
|
||||
int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; }
|
||||
|
||||
// in plugins use env->SubFrame()
|
||||
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const;
|
||||
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const;
|
||||
|
||||
|
||||
const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; }
|
||||
const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); }
|
||||
|
||||
bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); }
|
||||
|
||||
BYTE* GetWritePtr() const {
|
||||
if (vfb->GetRefcount()>1) {
|
||||
_ASSERT(FALSE);
|
||||
//throw AvisynthError("Internal Error - refcount was more than one!");
|
||||
}
|
||||
return IsWritable() ? (vfb->GetWritePtr() + offset) : 0;
|
||||
}
|
||||
|
||||
BYTE* GetWritePtr(int plane) const {
|
||||
if (plane==PLANAR_Y) {
|
||||
if (vfb->GetRefcount()>1) {
|
||||
_ASSERT(FALSE);
|
||||
// throw AvisynthError("Internal Error - refcount was more than one!");
|
||||
}
|
||||
return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0;
|
||||
}
|
||||
return vfb->data + GetOffset(plane);
|
||||
}
|
||||
|
||||
~VideoFrame() { InterlockedDecrement(&vfb->refcount); }
|
||||
};
|
||||
|
||||
enum {
|
||||
CACHE_NOTHING=0,
|
||||
CACHE_RANGE=1,
|
||||
CACHE_ALL=2,
|
||||
CACHE_AUDIO=3,
|
||||
CACHE_AUDIO_NONE=4
|
||||
};
|
||||
|
||||
// Base class for all filters.
|
||||
class IClip {
|
||||
friend class PClip;
|
||||
friend class AVSValue;
|
||||
int refcnt;
|
||||
void AddRef() { InterlockedIncrement((long *)&refcnt); }
|
||||
void Release() { InterlockedDecrement((long *)&refcnt); if (!refcnt) delete this; }
|
||||
public:
|
||||
IClip() : refcnt(0) {}
|
||||
|
||||
virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; }
|
||||
|
||||
virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0;
|
||||
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame
|
||||
virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples
|
||||
virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter.
|
||||
virtual const VideoInfo& __stdcall GetVideoInfo() = 0;
|
||||
virtual __stdcall ~IClip() {}
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to IClip
|
||||
class PClip {
|
||||
|
||||
IClip* p;
|
||||
|
||||
IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; }
|
||||
friend class AVSValue;
|
||||
friend class VideoFrame;
|
||||
|
||||
void Init(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PClip() { p = 0; }
|
||||
PClip(const PClip& x) { Init(x.p); }
|
||||
PClip(IClip* x) { Init(x); }
|
||||
void operator=(IClip* x) { Set(x); }
|
||||
void operator=(const PClip& x) { Set(x.p); }
|
||||
|
||||
IClip* operator->() const { return p; }
|
||||
|
||||
// useful in conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PClip() { if (p) p->Release(); }
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to VideoFrame
|
||||
class PVideoFrame {
|
||||
|
||||
VideoFrame* p;
|
||||
|
||||
void Init(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PVideoFrame() { p = 0; }
|
||||
PVideoFrame(const PVideoFrame& x) { Init(x.p); }
|
||||
PVideoFrame(VideoFrame* x) { Init(x); }
|
||||
void operator=(VideoFrame* x) { Set(x); }
|
||||
void operator=(const PVideoFrame& x) { Set(x.p); }
|
||||
|
||||
VideoFrame* operator->() const { return p; }
|
||||
|
||||
// for conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PVideoFrame() { if (p) p->Release();}
|
||||
};
|
||||
|
||||
|
||||
class AVSValue {
|
||||
public:
|
||||
|
||||
AVSValue() { type = 'v'; }
|
||||
AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); }
|
||||
AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); }
|
||||
AVSValue(bool b) { type = 'b'; boolean = b; }
|
||||
AVSValue(int i) { type = 'i'; integer = i; }
|
||||
// AVSValue(__int64 l) { type = 'l'; longlong = l; }
|
||||
AVSValue(float f) { type = 'f'; floating_pt = f; }
|
||||
AVSValue(double f) { type = 'f'; floating_pt = float(f); }
|
||||
AVSValue(const char* s) { type = 's'; string = s; }
|
||||
AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; }
|
||||
AVSValue(const AVSValue& v) { Assign(&v, true); }
|
||||
|
||||
~AVSValue() { if (IsClip() && clip) clip->Release(); }
|
||||
AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; }
|
||||
|
||||
// Note that we transparently allow 'int' to be treated as 'float'.
|
||||
// There are no int<->bool conversions, though.
|
||||
|
||||
bool Defined() const { return type != 'v'; }
|
||||
bool IsClip() const { return type == 'c'; }
|
||||
bool IsBool() const { return type == 'b'; }
|
||||
bool IsInt() const { return type == 'i'; }
|
||||
// bool IsLong() const { return (type == 'l'|| type == 'i'); }
|
||||
bool IsFloat() const { return type == 'f' || type == 'i'; }
|
||||
bool IsString() const { return type == 's'; }
|
||||
bool IsArray() const { return type == 'a'; }
|
||||
|
||||
PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; }
|
||||
bool AsBool() const { _ASSERTE(IsBool()); return boolean; }
|
||||
int AsInt() const { _ASSERTE(IsInt()); return integer; }
|
||||
// int AsLong() const { _ASSERTE(IsLong()); return longlong; }
|
||||
const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; }
|
||||
double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; }
|
||||
|
||||
bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; }
|
||||
int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; }
|
||||
double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; }
|
||||
const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; }
|
||||
|
||||
int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; }
|
||||
|
||||
const AVSValue& operator[](int index) const {
|
||||
_ASSERTE(IsArray() && index>=0 && index<array_size);
|
||||
return (IsArray() && index>=0 && index<array_size) ? array[index] : *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong
|
||||
short array_size;
|
||||
union {
|
||||
IClip* clip;
|
||||
bool boolean;
|
||||
int integer;
|
||||
float floating_pt;
|
||||
const char* string;
|
||||
const AVSValue* array;
|
||||
// __int64 longlong;
|
||||
};
|
||||
|
||||
void Assign(const AVSValue* src, bool init) {
|
||||
if (src->IsClip() && src->clip)
|
||||
src->clip->AddRef();
|
||||
if (!init && IsClip() && clip)
|
||||
clip->Release();
|
||||
// make sure this copies the whole struct!
|
||||
//((__int32*)this)[0] = ((__int32*)src)[0];
|
||||
//((__int32*)this)[1] = ((__int32*)src)[1];
|
||||
memcpy(this, src, sizeof(AVSValue));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// instantiable null filter
|
||||
class GenericVideoFilter : public IClip {
|
||||
protected:
|
||||
PClip child;
|
||||
VideoInfo vi;
|
||||
public:
|
||||
GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); }
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); }
|
||||
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); }
|
||||
const VideoInfo& __stdcall GetVideoInfo() { return vi; }
|
||||
bool __stdcall GetParity(int n) { return child->GetParity(n); }
|
||||
void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter.
|
||||
};
|
||||
|
||||
|
||||
class AvisynthError /* exception */ {
|
||||
public:
|
||||
const char* const msg;
|
||||
AvisynthError(const char* _msg) : msg(_msg) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* Helper classes useful to plugin authors */
|
||||
|
||||
class AlignPlanar : public GenericVideoFilter
|
||||
{
|
||||
public:
|
||||
AlignPlanar(PClip _clip);
|
||||
static PClip Create(PClip clip);
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FillBorder : public GenericVideoFilter
|
||||
{
|
||||
public:
|
||||
FillBorder(PClip _clip);
|
||||
static PClip Create(PClip clip);
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ConvertAudio : public GenericVideoFilter
|
||||
/**
|
||||
* Helper class to convert audio to any format
|
||||
**/
|
||||
{
|
||||
public:
|
||||
ConvertAudio(PClip _clip, int prefered_format);
|
||||
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
|
||||
void __stdcall SetCacheHints(int cachehints,int frame_range); // We do pass cache requests upwards, to the cache!
|
||||
|
||||
static PClip Create(PClip clip, int sample_type, int prefered_type);
|
||||
static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_24bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_8bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
virtual ~ConvertAudio();
|
||||
|
||||
private:
|
||||
void convertToFloat(char* inbuf, float* outbuf, char sample_type, int count);
|
||||
void convertToFloat_3DN(char* inbuf, float* outbuf, char sample_type, int count);
|
||||
void convertToFloat_SSE(char* inbuf, float* outbuf, char sample_type, int count);
|
||||
void convertToFloat_SSE2(char* inbuf, float* outbuf, char sample_type, int count);
|
||||
void convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count);
|
||||
void convertFromFloat_3DN(float* inbuf, void* outbuf, char sample_type, int count);
|
||||
void convertFromFloat_SSE(float* inbuf, void* outbuf, char sample_type, int count);
|
||||
void convertFromFloat_SSE2(float* inbuf, void* outbuf, char sample_type, int count);
|
||||
|
||||
__inline int Saturate_int8(float n);
|
||||
__inline short Saturate_int16(float n);
|
||||
__inline int Saturate_int24(float n);
|
||||
__inline int Saturate_int32(float n);
|
||||
|
||||
char src_format;
|
||||
char dst_format;
|
||||
int src_bps;
|
||||
char *tempbuffer;
|
||||
SFLOAT *floatbuffer;
|
||||
int tempbuffer_size;
|
||||
};
|
||||
|
||||
|
||||
// For GetCPUFlags. These are backwards-compatible with those in VirtualDub.
|
||||
enum {
|
||||
/* slowest CPU to support extension */
|
||||
CPUF_FORCE = 0x01, // N/A
|
||||
CPUF_FPU = 0x02, // 386/486DX
|
||||
CPUF_MMX = 0x04, // P55C, K6, PII
|
||||
CPUF_INTEGER_SSE = 0x08, // PIII, Athlon
|
||||
CPUF_SSE = 0x10, // PIII, Athlon XP/MP
|
||||
CPUF_SSE2 = 0x20, // PIV, Hammer
|
||||
CPUF_3DNOW = 0x40, // K6-2
|
||||
CPUF_3DNOW_EXT = 0x80, // Athlon
|
||||
CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which only Hammer
|
||||
// will have anyway)
|
||||
CPUF_SSE3 = 0x100, // Some P4 & Athlon 64.
|
||||
};
|
||||
#define MAX_INT 0x7fffffff
|
||||
#define MIN_INT -0x7fffffff
|
||||
|
||||
|
||||
|
||||
class IScriptEnvironment {
|
||||
public:
|
||||
virtual __stdcall ~IScriptEnvironment() {}
|
||||
|
||||
virtual /*static*/ long __stdcall GetCPUFlags() = 0;
|
||||
|
||||
virtual char* __stdcall SaveString(const char* s, int length = -1) = 0;
|
||||
virtual char* __stdcall Sprintf(const char* fmt, ...) = 0;
|
||||
// note: val is really a va_list; I hope everyone typedefs va_list to a pointer
|
||||
virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0;
|
||||
|
||||
__declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0;
|
||||
|
||||
class NotFound /*exception*/ {}; // thrown by Invoke and GetVar
|
||||
|
||||
typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env);
|
||||
|
||||
virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0;
|
||||
virtual bool __stdcall FunctionExists(const char* name) = 0;
|
||||
virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0;
|
||||
|
||||
virtual AVSValue __stdcall GetVar(const char* name) = 0;
|
||||
virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0;
|
||||
virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0;
|
||||
|
||||
virtual void __stdcall PushContext(int level=0) = 0;
|
||||
virtual void __stdcall PopContext() = 0;
|
||||
|
||||
// align should be 4 or 8
|
||||
virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0;
|
||||
|
||||
virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0;
|
||||
|
||||
virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0;
|
||||
|
||||
typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env);
|
||||
virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0;
|
||||
|
||||
virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0;
|
||||
|
||||
virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0;
|
||||
|
||||
virtual int __stdcall SetMemoryMax(int mem) = 0;
|
||||
|
||||
virtual int __stdcall SetWorkingDir(const char * newdir) = 0;
|
||||
|
||||
virtual void* __stdcall ManageCache(int key, void* data) = 0;
|
||||
|
||||
enum PlanarChromaAlignmentMode {
|
||||
PlanarChromaAlignmentOff,
|
||||
PlanarChromaAlignmentOn,
|
||||
PlanarChromaAlignmentTest };
|
||||
|
||||
virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0;
|
||||
|
||||
virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0;
|
||||
};
|
||||
|
||||
|
||||
// avisynth.dll exports this; it's a way to use it as a library, without
|
||||
// writing an AVS script or without going through AVIFile.
|
||||
IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION);
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //__AVISYNTH_H__
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
#ifdef WITH_AVISYNTH
|
||||
#include "avisynth_wrap.h"
|
||||
|
||||
#include "avisynth.h"
|
||||
#include <avisynth.h>
|
||||
#include "options.h"
|
||||
|
||||
#include <mutex>
|
||||
|
|
BIN
src/bitmaps/button/button_align_16.png
Normal file
BIN
src/bitmaps/button/button_align_16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 353 B |
BIN
src/bitmaps/button/button_align_24.png
Normal file
BIN
src/bitmaps/button/button_align_24.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 571 B |
BIN
src/bitmaps/button/button_align_32.png
Normal file
BIN
src/bitmaps/button/button_align_32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 690 B |
BIN
src/bitmaps/button/button_align_48.png
Normal file
BIN
src/bitmaps/button/button_align_48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
src/bitmaps/button/button_align_64.png
Normal file
BIN
src/bitmaps/button/button_align_64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 547 B |
|
@ -51,6 +51,11 @@ button/bugtracker_button_24.png
|
|||
button/bugtracker_button_32.png
|
||||
button/bugtracker_button_48.png
|
||||
button/bugtracker_button_64.png
|
||||
button/button_align_16.png
|
||||
button/button_align_24.png
|
||||
button/button_align_32.png
|
||||
button/button_align_48.png
|
||||
button/button_align_64.png
|
||||
button/button_audio_commit_16.png
|
||||
button/button_audio_commit_24.png
|
||||
button/button_audio_commit_32.png
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
|
||||
#include "dialogs.h"
|
||||
|
||||
#if BOOST_VERSION >= 106900
|
||||
#include <boost/gil.hpp>
|
||||
#else
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
#endif
|
||||
|
||||
AGI_DEFINE_EVENT(EVT_COLOR, agi::Color);
|
||||
AGI_DEFINE_EVENT(EVT_COLOR, agi::Color)
|
||||
|
||||
ColourButton::ColourButton(wxWindow *parent, wxSize const& size, bool alpha, agi::Color col, wxValidator const& validator)
|
||||
: wxButton(parent, -1, "", wxDefaultPosition, wxSize(size.GetWidth() + 6, size.GetHeight() + 6), 0, validator)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/// Emitted by ColourButton when the user picks a new color, with the chosen
|
||||
/// color set to the event payload
|
||||
AGI_DECLARE_EVENT(EVT_COLOR, agi::Color);
|
||||
AGI_DECLARE_EVENT(EVT_COLOR, agi::Color)
|
||||
|
||||
/// A button which displays a currently-selected color and lets the user pick
|
||||
/// a new color when clicked
|
||||
|
@ -43,6 +43,12 @@ public:
|
|||
|
||||
/// Get the currently selected color
|
||||
agi::Color GetColor() { return colour; }
|
||||
|
||||
void SetColor(agi::Color color)
|
||||
{
|
||||
colour = color;
|
||||
UpdateBitmap();
|
||||
}
|
||||
};
|
||||
|
||||
struct ColorValidator final : public wxValidator {
|
||||
|
|
|
@ -35,10 +35,10 @@ namespace agi { struct Context; }
|
|||
#define CMD_TYPE(a) int Type() const override { using namespace cmd; return a; }
|
||||
|
||||
#define CMD_ICON(icon) wxBitmap Icon(int size, wxLayoutDirection dir = wxLayout_LeftToRight) const override { \
|
||||
if (size == 64) return GETIMAGEDIR(icon##_64, dir); \
|
||||
if (size == 48) return GETIMAGEDIR(icon##_48, dir); \
|
||||
if (size == 32) return GETIMAGEDIR(icon##_32, dir); \
|
||||
if (size == 24) return GETIMAGEDIR(icon##_24, dir); \
|
||||
if (size >= 64) return GETIMAGEDIR(icon##_64, dir); \
|
||||
if (size >= 48) return GETIMAGEDIR(icon##_48, dir); \
|
||||
if (size >= 32) return GETIMAGEDIR(icon##_32, dir); \
|
||||
if (size >= 24) return GETIMAGEDIR(icon##_24, dir); \
|
||||
return GETIMAGEDIR(icon##_16, dir); \
|
||||
}
|
||||
|
||||
|
|
|
@ -672,7 +672,7 @@ static void duplicate_lines(agi::Context *c, int shift) {
|
|||
// after the selected block
|
||||
do {
|
||||
auto old_diag = &*start;
|
||||
auto new_diag = new AssDialogue(*old_diag);
|
||||
auto new_diag = new AssDialogue(*old_diag);
|
||||
|
||||
c->ass->Events.insert(insert_pos, *new_diag);
|
||||
new_sel.insert(new_diag);
|
||||
|
@ -697,8 +697,8 @@ static void duplicate_lines(agi::Context *c, int shift) {
|
|||
new_diag->Start = c->videoController->TimeAtFrame(cur_frame, agi::vfr::START);
|
||||
}
|
||||
else {
|
||||
old_diag->Start = c->videoController->TimeAtFrame(cur_frame + 1, agi::vfr::START);
|
||||
new_diag->End = c->videoController->TimeAtFrame(cur_frame, agi::vfr::END);
|
||||
old_diag->End = c->videoController->TimeAtFrame(cur_frame, agi::vfr::END);
|
||||
new_diag->Start = c->videoController->TimeAtFrame(cur_frame + 1, agi::vfr::START);
|
||||
}
|
||||
|
||||
/// @todo also split \t and \move?
|
||||
|
|
|
@ -59,7 +59,7 @@ struct help_bugs final : public Command {
|
|||
throw c->parent;
|
||||
}
|
||||
}
|
||||
wxLaunchDefaultBrowser("http://devel.aegisub.org/", wxBROWSER_NEW_WINDOW);
|
||||
wxLaunchDefaultBrowser("https://github.com/Aegisub/Aegisub/issues", wxBROWSER_NEW_WINDOW);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -75,18 +75,6 @@ struct help_contents final : public Command {
|
|||
}
|
||||
};
|
||||
|
||||
struct help_forums final : public Command {
|
||||
CMD_NAME("help/forums")
|
||||
CMD_ICON(forums_button)
|
||||
STR_MENU("&Forums")
|
||||
STR_DISP("Forums")
|
||||
STR_HELP("Visit Aegisub's forums")
|
||||
|
||||
void operator()(agi::Context *) override {
|
||||
wxLaunchDefaultBrowser("http://forum.aegisub.org/", wxBROWSER_NEW_WINDOW);
|
||||
}
|
||||
};
|
||||
|
||||
struct help_irc final : public Command {
|
||||
CMD_NAME("help/irc")
|
||||
CMD_ICON(irc_button)
|
||||
|
@ -128,7 +116,6 @@ namespace cmd {
|
|||
void init_help() {
|
||||
reg(agi::make_unique<help_bugs>());
|
||||
reg(agi::make_unique<help_contents>());
|
||||
reg(agi::make_unique<help_forums>());
|
||||
reg(agi::make_unique<help_irc>());
|
||||
reg(agi::make_unique<help_video>());
|
||||
reg(agi::make_unique<help_website>());
|
||||
|
|
|
@ -235,6 +235,18 @@ struct time_snap_scene final : public validate_video_loaded {
|
|||
}
|
||||
};
|
||||
|
||||
struct time_align_subtitle_to_point final : public validate_video_loaded {
|
||||
CMD_NAME("time/align")
|
||||
CMD_ICON(button_align)
|
||||
STR_MENU("Align subtitle to video")
|
||||
STR_DISP("Align subtitle to video")
|
||||
STR_HELP("Align subtitle to video by key points")
|
||||
void operator()(agi::Context* c) override {
|
||||
c->videoController->Stop();
|
||||
ShowAlignToVideoDialog(c);
|
||||
}
|
||||
};
|
||||
|
||||
struct time_add_lead_both final : public Command {
|
||||
CMD_NAME("time/lead/both")
|
||||
STR_MENU("Add lead in and out")
|
||||
|
@ -393,6 +405,7 @@ namespace cmd {
|
|||
reg(agi::make_unique<time_snap_end_video>());
|
||||
reg(agi::make_unique<time_snap_scene>());
|
||||
reg(agi::make_unique<time_snap_start_video>());
|
||||
reg(agi::make_unique<time_align_subtitle_to_point>());
|
||||
reg(agi::make_unique<time_start_decrease>());
|
||||
reg(agi::make_unique<time_start_increase>());
|
||||
}
|
||||
|
|
|
@ -49,10 +49,11 @@ void ShowAboutDialog(wxWindow *parent) {
|
|||
|
||||
// Generate about string
|
||||
wxString aboutString = wxString("Aegisub ") + GetAegisubShortVersionString() + ".\n"
|
||||
"Copyright (c) 2005-2014 Rodrigo Braz Monteiro, Niels Martin Hansen, Thomas Goyne et al.\n\n"
|
||||
"Copyright (c) 2005-2019 Rodrigo Braz Monteiro, Niels Martin Hansen, Thomas Goyne et al.\n\n"
|
||||
"Programmers:\n"
|
||||
" Alysson Souza e Silva\n"
|
||||
" Amar Takhar\n"
|
||||
" Charlie Jiang\n"
|
||||
" Dan Donovan\n"
|
||||
" Daniel Moscoviter\n"
|
||||
" David Conrad\n"
|
||||
|
@ -67,6 +68,7 @@ void ShowAboutDialog(wxWindow *parent) {
|
|||
" Muhammad Lukman Nasaruddin\n"
|
||||
" Niels Martin Hansen\n"
|
||||
" Patryk Pomykalski\n"
|
||||
" Qirui Wang\n"
|
||||
" Ravi Pinjala\n"
|
||||
" Rodrigo Braz Monteiro\n"
|
||||
" Simone Cociancich\n"
|
||||
|
@ -129,7 +131,7 @@ void ShowAboutDialog(wxWindow *parent) {
|
|||
wxChar copySymbol = 0xA9;
|
||||
aboutString.Replace("(c)", wxString(copySymbol));
|
||||
|
||||
wxTextCtrl *textctrl = new wxTextCtrl(&d, -1, aboutString, wxDefaultPosition, wxSize(-1, 200), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_NONE);
|
||||
wxTextCtrl *textctrl = new wxTextCtrl(&d, -1, aboutString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxBORDER_NONE);
|
||||
|
||||
wxSizer *MainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
MainSizer->Add(new wxStaticBitmap(&d, -1, GETIMAGE(splash)), 0, wxCENTER, 0);
|
||||
|
|
378
src/dialog_align.cpp
Normal file
378
src/dialog_align.cpp
Normal file
|
@ -0,0 +1,378 @@
|
|||
// Copyright (c) 2019, Charlie Jiang
|
||||
// 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/
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "compat.h"
|
||||
#include "dialog_manager.h"
|
||||
#include "format.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "video_frame.h"
|
||||
#include "libresrc/libresrc.h"
|
||||
#include "options.h"
|
||||
#include "project.h"
|
||||
#include "selection_controller.h"
|
||||
#include "video_controller.h"
|
||||
#include "async_video_provider.h"
|
||||
#include "colour_button.h"
|
||||
#include "image_position_picker.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <libaegisub/ass/time.h>
|
||||
#include <libaegisub/vfr.h>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/textctrl.h>
|
||||
#if BOOST_VERSION >= 106900
|
||||
#include <boost/gil.hpp>
|
||||
#else
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
class DialogAlignToVideo final : public wxDialog {
|
||||
agi::Context* context;
|
||||
AsyncVideoProvider* provider;
|
||||
|
||||
wxImage preview_image;
|
||||
VideoFrame current_frame;
|
||||
int current_n_frame;
|
||||
|
||||
ImagePositionPicker* preview_frame;
|
||||
ColourButton* selected_color;
|
||||
wxTextCtrl* selected_x;
|
||||
wxTextCtrl* selected_y;
|
||||
wxTextCtrl* selected_tolerance;
|
||||
|
||||
void update_from_textbox();
|
||||
void update_from_textbox(wxCommandEvent&);
|
||||
|
||||
bool check_exists(int pos, int x, int y, int* lrud, double* orig, unsigned char tolerance);
|
||||
void process(wxCommandEvent&);
|
||||
public:
|
||||
DialogAlignToVideo(agi::Context* context);
|
||||
~DialogAlignToVideo();
|
||||
};
|
||||
|
||||
DialogAlignToVideo::DialogAlignToVideo(agi::Context* context)
|
||||
: wxDialog(context->parent, -1, _("Align subtitle to video by key point"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxRESIZE_BORDER)
|
||||
, context(context), provider(context->project->VideoProvider())
|
||||
{
|
||||
auto add_with_label = [&](wxSizer * sizer, wxString const& label, wxWindow * ctrl) {
|
||||
sizer->Add(new wxStaticText(this, -1, label), 0, wxLEFT | wxRIGHT | wxCENTER, 3);
|
||||
sizer->Add(ctrl, 1, wxLEFT);
|
||||
};
|
||||
|
||||
auto tolerance = OPT_GET("Tool/Align to Video/Tolerance")->GetInt();
|
||||
auto maximized = OPT_GET("Tool/Align to Video/Maximized")->GetBool();
|
||||
|
||||
current_n_frame = context->videoController->GetFrameN();
|
||||
current_frame = *context->project->VideoProvider()->GetFrame(current_n_frame, 0, true);
|
||||
preview_image = GetImage(current_frame);
|
||||
|
||||
preview_frame = new ImagePositionPicker(this, preview_image, [&](int x, int y, unsigned char r, unsigned char g, unsigned char b) -> void {
|
||||
selected_x->ChangeValue(wxString::Format(wxT("%i"), x));
|
||||
selected_y->ChangeValue(wxString::Format(wxT("%i"), y));
|
||||
|
||||
selected_color->SetColor(agi::Color(r, g, b));
|
||||
});
|
||||
selected_color = new ColourButton(this, wxSize(55, 16), true, agi::Color("FFFFFF"));
|
||||
selected_color->SetToolTip(_("The key color to be followed."));
|
||||
selected_x = new wxTextCtrl(this, -1, "0");
|
||||
selected_x->SetToolTip(_("The x coord of the key point."));
|
||||
selected_y = new wxTextCtrl(this, -1, "0");
|
||||
selected_y->SetToolTip(_("The y coord of the key point."));
|
||||
selected_tolerance = new wxTextCtrl(this, -1, wxString::Format(wxT("%i"), int(tolerance)));
|
||||
selected_tolerance->SetToolTip(_("Max tolerance of the color."));
|
||||
|
||||
selected_x->Bind(wxEVT_TEXT, &DialogAlignToVideo::update_from_textbox, this);
|
||||
selected_y->Bind(wxEVT_TEXT, &DialogAlignToVideo::update_from_textbox, this);
|
||||
update_from_textbox();
|
||||
|
||||
wxFlexGridSizer* right_sizer = new wxFlexGridSizer(4, 2, 5, 5);
|
||||
add_with_label(right_sizer, _("X"), selected_x);
|
||||
add_with_label(right_sizer, _("Y"), selected_y);
|
||||
add_with_label(right_sizer, _("Color"), selected_color);
|
||||
add_with_label(right_sizer, _("Tolerance"), selected_tolerance);
|
||||
right_sizer->AddGrowableCol(1, 1);
|
||||
|
||||
wxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
main_sizer->Add(preview_frame, 1, (wxALL & ~wxRIGHT) | wxEXPAND, 5);
|
||||
main_sizer->Add(right_sizer, 0, wxALIGN_LEFT, 5);
|
||||
|
||||
wxSizer* dialog_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
dialog_sizer->Add(main_sizer, wxSizerFlags(1).Border(wxALL & ~wxBOTTOM).Expand());
|
||||
dialog_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Right().Border());
|
||||
SetSizerAndFit(dialog_sizer);
|
||||
SetSize(1024, 700);
|
||||
CenterOnParent();
|
||||
|
||||
Bind(wxEVT_BUTTON, &DialogAlignToVideo::process, this, wxID_OK);
|
||||
SetIcon(GETICON(button_align_16));
|
||||
if (maximized)
|
||||
wxDialog::Maximize(true);
|
||||
}
|
||||
|
||||
DialogAlignToVideo::~DialogAlignToVideo()
|
||||
{
|
||||
long lt;
|
||||
if (!selected_tolerance->GetValue().ToLong(<))
|
||||
return;
|
||||
if (lt < 0 || lt > 255)
|
||||
return;
|
||||
|
||||
OPT_SET("Tool/Align to Video/Tolerance")->SetInt(lt);
|
||||
}
|
||||
|
||||
void rgb2lab(unsigned char r, unsigned char g, unsigned char b, double* lab)
|
||||
{
|
||||
double R = static_cast<double>(r) / 255.0;
|
||||
double G = static_cast<double>(g) / 255.0;
|
||||
double B = static_cast<double>(b) / 255.0;
|
||||
double X = 0.412453 * R + 0.357580 * G + 0.180423 * B;
|
||||
double Y = 0.212671 * R + 0.715160 * G + 0.072169 * B;
|
||||
double Z = 0.019334 * R + 0.119193 * G + 0.950227 * B;
|
||||
double xr = X / 0.950456, yr = Y / 1.000, zr = Z / 1.088854;
|
||||
|
||||
if (yr > 0.008856) {
|
||||
lab[0] = 116.0 * pow(yr, 1.0 / 3.0) - 16.0;
|
||||
}
|
||||
else {
|
||||
lab[0] = 903.3 * yr;
|
||||
}
|
||||
|
||||
double fxr, fyr, fzr;
|
||||
if (xr > 0.008856)
|
||||
fxr = pow(xr, 1.0 / 3.0);
|
||||
else
|
||||
fxr = 7.787 * xr + 16.0 / 116.0;
|
||||
|
||||
if (yr > 0.008856)
|
||||
fyr = pow(yr, 1.0 / 3.0);
|
||||
else
|
||||
fyr = 7.787 * yr + 16.0 / 116.0;
|
||||
|
||||
if (zr > 0.008856)
|
||||
fzr = pow(zr, 1.0 / 3.0);
|
||||
else
|
||||
fzr = 7.787 * zr + 16.0 / 116.0;
|
||||
|
||||
lab[1] = 500.0 * (fxr - fyr);
|
||||
lab[2] = 200.0 * (fyr - fzr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool check_point(boost::gil::pixel<unsigned char, T> & pixel, double orig[3], unsigned char tolerance)
|
||||
{
|
||||
double lab[3];
|
||||
// in pixel: B,G,R
|
||||
rgb2lab(pixel[2], pixel[1], pixel[0], lab);
|
||||
auto diff = sqrt(pow(lab[0] - orig[0], 2) + pow(lab[1] - orig[1], 2) + pow(lab[2] - orig[2], 2));
|
||||
return diff < tolerance;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool calculate_point(boost::gil::image_view<T> view, int x, int y, double orig[3], unsigned char tolerance, int* ret)
|
||||
{
|
||||
auto origin = *view.at(x, y);
|
||||
if (!check_point(origin, orig, tolerance))
|
||||
return false;
|
||||
auto w = view.width();
|
||||
auto h = view.height();
|
||||
int l = x, r = x, u = y, d = y;
|
||||
for (int i = x + 1; i < w; i++)
|
||||
{
|
||||
auto p = *view.at(i, y);
|
||||
if (!check_point(p, orig, tolerance))
|
||||
{
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = x - 1; i >= 0; i--)
|
||||
{
|
||||
auto p = *view.at(i, y);
|
||||
if (!check_point(p, orig, tolerance))
|
||||
{
|
||||
l = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = y + 1; i < h; i++)
|
||||
{
|
||||
auto p = *view.at(x, i);
|
||||
if (!check_point(p, orig, tolerance))
|
||||
{
|
||||
d = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = y - 1; i >= 0; i--)
|
||||
{
|
||||
auto p = *view.at(x, i);
|
||||
if (!check_point(p, orig, tolerance))
|
||||
{
|
||||
u = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret[0] = l;
|
||||
ret[1] = r;
|
||||
ret[2] = u;
|
||||
ret[3] = d;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DialogAlignToVideo::process(wxCommandEvent & evt)
|
||||
{
|
||||
auto n_frames = provider->GetFrameCount();
|
||||
auto w = provider->GetWidth();
|
||||
auto h = provider->GetHeight();
|
||||
|
||||
long lx, ly, lt;
|
||||
if (!selected_x->GetValue().ToLong(&lx) || !selected_y->GetValue().ToLong(&ly) || !selected_tolerance->GetValue().ToLong(<))
|
||||
{
|
||||
wxMessageBox(_("Bad x or y position or tolerance value!"));
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
if (lx < 0 || ly < 0 || lx >= w || ly >= h)
|
||||
{
|
||||
wxMessageBox(wxString::Format(_("Bad x or y position! Require: 0 <= x < %i, 0 <= y < %i"), w, h));
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
if (lt < 0 || lt > 255)
|
||||
{
|
||||
wxMessageBox(_("Bad tolerance value! Require: 0 <= torlerance <= 255"));
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
int x = int(lx), y = int(ly);
|
||||
unsigned char tolerance = (unsigned char)(lt);
|
||||
|
||||
auto color = selected_color->GetColor();
|
||||
auto r = color.r;
|
||||
auto b = color.b;
|
||||
auto g = color.g;
|
||||
double lab[3];
|
||||
rgb2lab(r, g, b, lab);
|
||||
|
||||
int pos = current_n_frame;
|
||||
auto frame = provider->GetFrame(pos, -1, true);
|
||||
auto view = interleaved_view(frame->width, frame->height, reinterpret_cast<boost::gil::bgra8_pixel_t*>(frame->data.data()), frame->pitch);
|
||||
if (frame->flipped)
|
||||
y = frame->height - y;
|
||||
int lrud[4];
|
||||
calculate_point(view, x, y, lab, tolerance, lrud);
|
||||
|
||||
// find forward
|
||||
#define CHECK_EXISTS_POS check_exists(pos, x, y, lrud, lab, tolerance)
|
||||
while (pos >= 0)
|
||||
{
|
||||
if (CHECK_EXISTS_POS)
|
||||
pos -= 2;
|
||||
else break;
|
||||
}
|
||||
pos++;
|
||||
pos = std::max(0, pos);
|
||||
auto left = CHECK_EXISTS_POS ? pos : pos + 1;
|
||||
|
||||
pos = current_n_frame;
|
||||
while (pos < n_frames)
|
||||
{
|
||||
if (CHECK_EXISTS_POS)
|
||||
pos += 2;
|
||||
else break;
|
||||
}
|
||||
pos--;
|
||||
pos = std::min(pos, n_frames - 1);
|
||||
auto right = CHECK_EXISTS_POS ? pos : pos - 1;
|
||||
|
||||
auto timecode = context->project->Timecodes();
|
||||
auto line = context->selectionController->GetActiveLine();
|
||||
line->Start = timecode.TimeAtFrame(left, agi::vfr::Time::START);
|
||||
line->End = timecode.TimeAtFrame(right, agi::vfr::Time::END); // exclusive
|
||||
context->ass->Commit(_("Align to video by key point"), AssFile::COMMIT_DIAG_TIME);
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DialogAlignToVideo::check_exists(int pos, int x, int y, int* lrud, double* orig, unsigned char tolerance)
|
||||
{
|
||||
auto frame = provider->GetFrame(pos, -1, true);
|
||||
auto view = interleaved_view(frame->width, frame->height, reinterpret_cast<boost::gil::bgra8_pixel_t*>(frame->data.data()), frame->pitch);
|
||||
if (frame->flipped)
|
||||
y = frame->height - y;
|
||||
int actual[4];
|
||||
if (!calculate_point(view, x, y, orig, tolerance, actual)) return false;
|
||||
int dl = abs(actual[0] - lrud[0]);
|
||||
int dr = abs(actual[1] - lrud[1]);
|
||||
int du = abs(actual[2] - lrud[2]);
|
||||
int dd = abs(actual[3] - lrud[3]);
|
||||
|
||||
return dl <= 5 && dr <= 5 && du <= 5 && dd <= 5;
|
||||
}
|
||||
|
||||
void DialogAlignToVideo::update_from_textbox()
|
||||
{
|
||||
long lx, ly;
|
||||
int w = preview_image.GetWidth(), h = preview_image.GetHeight();
|
||||
if (!selected_x->GetValue().ToLong(&lx) || !selected_y->GetValue().ToLong(&ly))
|
||||
return;
|
||||
|
||||
if (lx < 0 || ly < 0 || lx >= w || ly >= h)
|
||||
return;
|
||||
int x = int(lx);
|
||||
int y = int(ly);
|
||||
auto r = preview_image.GetRed(x, y);
|
||||
auto g = preview_image.GetGreen(x, y);
|
||||
auto b = preview_image.GetBlue(x, y);
|
||||
selected_color->SetColor(agi::Color(r, g, b));
|
||||
}
|
||||
|
||||
void DialogAlignToVideo::update_from_textbox(wxCommandEvent & evt)
|
||||
{
|
||||
update_from_textbox();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ShowAlignToVideoDialog(agi::Context * c)
|
||||
{
|
||||
c->dialog->Show<DialogAlignToVideo>(c);
|
||||
}
|
|
@ -143,7 +143,7 @@ void DialogAutosave::Populate(std::map<wxString, AutosaveFile> &files_map, std::
|
|||
|
||||
auto it = files_map.find(name);
|
||||
if (it == files_map.end())
|
||||
it = files_map.insert({name, AutosaveFile{name}}).first;
|
||||
it = files_map.insert({name, AutosaveFile{name, std::vector<Version>()}}).first;
|
||||
it->second.versions.push_back(Version{wxFileName(directory, fn).GetFullPath(), date, agi::wxformat(name_fmt, date.Format())});
|
||||
} while (dir.GetNext(&fn));
|
||||
}
|
||||
|
|
|
@ -557,9 +557,9 @@ DialogColorPicker::DialogColorPicker(wxWindow *parent, agi::Color initial_color,
|
|||
wxString modes[] = { _("RGB/R"), _("RGB/G"), _("RGB/B"), _("HSL/L"), _("HSV/H") };
|
||||
colorspace_choice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 5, modes);
|
||||
|
||||
wxSize colorinput_size = GetTextExtent(" &H10117B& ");
|
||||
colorinput_size.SetHeight(-1);
|
||||
wxSize colorinput_labelsize(40, -1);
|
||||
ass_input = new wxTextCtrl(this, -1);
|
||||
wxSize colorinput_size = ass_input->GetSizeFromTextSize(GetTextExtent(wxS("&H10117B&")));
|
||||
ass_input->SetInitialSize(colorinput_size);
|
||||
|
||||
wxSizer *rgb_box = new wxStaticBoxSizer(wxHORIZONTAL, this, _("RGB color"));
|
||||
wxSizer *hsl_box = new wxStaticBoxSizer(wxVERTICAL, this, _("HSL color"));
|
||||
|
@ -568,7 +568,7 @@ DialogColorPicker::DialogColorPicker(wxWindow *parent, agi::Color initial_color,
|
|||
for (auto& elem : rgb_input)
|
||||
elem = new wxSpinCtrl(this, -1, "", wxDefaultPosition, colorinput_size, wxSP_ARROW_KEYS, 0, 255);
|
||||
|
||||
ass_input = new wxTextCtrl(this, -1, "", wxDefaultPosition, colorinput_size);
|
||||
// ass_input = new wxTextCtrl(this, -1, "", wxDefaultPosition, colorinput_size);
|
||||
html_input = new wxTextCtrl(this, -1, "", wxDefaultPosition, colorinput_size);
|
||||
alpha_input = new wxSpinCtrl(this, -1, "", wxDefaultPosition, colorinput_size, wxSP_ARROW_KEYS, 0, 255);
|
||||
|
||||
|
|
|
@ -72,19 +72,22 @@ static ResolutionShortcut resolutions[] = {
|
|||
{"704x396 (SD widescreen)", 704, 396},
|
||||
{"640x352 (SD widescreen MOD16)", 640, 352},
|
||||
{"704x400 (SD widescreen MOD16)", 704, 400},
|
||||
{"1024x576 (SuperPAL widescreen)", 1024, 576},
|
||||
{"1280x720 (HD 720p)", 1280, 720},
|
||||
{"1920x1080 (HD 1080p)", 1920, 1080},
|
||||
{"1024x576 (SuperPAL widescreen)", 1024, 576}
|
||||
{"1920x1080 (FHD 1080p)", 1920, 1080},
|
||||
{"2560x1440 (QHD 1440p)", 2560, 1440},
|
||||
{"3840x2160 (4K UHD 2160p)", 3840, 2160},
|
||||
};
|
||||
|
||||
wxSpinCtrl *spin_ctrl(wxWindow *parent, int min, int max, int *value) {
|
||||
auto ctrl = new wxSpinCtrl(parent, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, min, max, *value);
|
||||
auto ctrl = new wxSpinCtrl(parent, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, min, max, *value);
|
||||
ctrl->SetValidator(wxGenericValidator(value));
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
// FIXME: change the misleading function name, this is TextCtrl in fact
|
||||
wxControl *spin_ctrl(wxWindow *parent, double min, double max, double *value) {
|
||||
return new wxTextCtrl(parent, -1, "", wxDefaultPosition, wxSize(50, -1), 0, DoubleValidator(value, min, max));
|
||||
return new wxTextCtrl(parent, -1, "", wxDefaultPosition, wxDefaultSize, 0, DoubleValidator(value, min, max));
|
||||
}
|
||||
|
||||
wxComboBox *resolution_shortcuts(wxWindow *parent, int width, int height) {
|
||||
|
|
|
@ -110,6 +110,7 @@ int ShowEbuExportConfigurationDialog(wxWindow *owner, EbuExportSettings &s) {
|
|||
wxRadioBox *tv_standard_box = new wxRadioBox(&d, -1, _("TV standard"), wxDefaultPosition, wxDefaultSize, 6, tv_standards, 0, wxRA_SPECIFY_ROWS);
|
||||
|
||||
wxTextCtrl *timecode_offset_entry = new wxTextCtrl(&d, -1, "00:00:00:00");
|
||||
timecode_offset_entry->SetInitialSize(timecode_offset_entry->GetSizeFromTextSize(timecode_offset_entry->GetTextExtent(wxS("00:00:00:00"))));
|
||||
wxCheckBox *inclusive_end_times_check = new wxCheckBox(&d, -1, _("Out-times are inclusive"));
|
||||
|
||||
wxString text_encodings[] = {
|
||||
|
@ -129,7 +130,8 @@ int ShowEbuExportConfigurationDialog(wxWindow *owner, EbuExportSettings &s) {
|
|||
_("Skip lines that are too long")
|
||||
};
|
||||
|
||||
wxSpinCtrl *max_line_length_ctrl = new wxSpinCtrl(&d, -1, wxString(), wxDefaultPosition, wxSize(65, -1));
|
||||
wxSpinCtrl *max_line_length_ctrl = new wxSpinCtrl(&d, -1, wxString());
|
||||
max_line_length_ctrl->SetInitialSize(max_line_length_ctrl->GetSizeFromTextSize(max_line_length_ctrl->GetTextExtent(wxS("00"))));
|
||||
wxComboBox *wrap_mode_ctrl = new wxComboBox(&d, -1, wrap_modes[0], wxDefaultPosition, wxDefaultSize, 4, wrap_modes, wxCB_DROPDOWN | wxCB_READONLY);
|
||||
wxCheckBox *translate_alignments_check = new wxCheckBox(&d, -1, _("Translate alignments"));
|
||||
|
||||
|
|
|
@ -400,7 +400,11 @@ void DialogFontsCollector::OnAddText(ValueEvent<color_str_pair> &event) {
|
|||
auto const& utf8 = str.second.utf8_str();
|
||||
collection_log->AppendTextRaw(utf8.data(), utf8.length());
|
||||
if (str.first) {
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
collection_log->StartStyling(pos);
|
||||
#else
|
||||
collection_log->StartStyling(pos, 31);
|
||||
#endif
|
||||
collection_log->SetStyling(utf8.length(), str.first);
|
||||
}
|
||||
collection_log->GotoPos(pos + utf8.length());
|
||||
|
@ -415,8 +419,7 @@ void DialogFontsCollector::OnCollectionComplete(wxThreadEvent &) {
|
|||
if (path.Decode("?script") == "?script")
|
||||
collection_mode->Enable(2, false);
|
||||
|
||||
wxCommandEvent evt;
|
||||
OnRadio(evt);
|
||||
UpdateControls();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,8 +108,8 @@ DialogProperties::DialogProperties(agi::Context *c)
|
|||
TopSizer->Add(TopSizerGrid,1,wxALL | wxEXPAND,0);
|
||||
|
||||
// Resolution box
|
||||
ResX = new wxTextCtrl(&d,-1,"",wxDefaultPosition,wxSize(50,20),0,IntValidator(c->ass->GetScriptInfoAsInt("PlayResX")));
|
||||
ResY = new wxTextCtrl(&d,-1,"",wxDefaultPosition,wxSize(50,20),0,IntValidator(c->ass->GetScriptInfoAsInt("PlayResY")));
|
||||
ResX = new wxTextCtrl(&d,-1,"",wxDefaultPosition,wxDefaultSize,0,IntValidator(c->ass->GetScriptInfoAsInt("PlayResX")));
|
||||
ResY = new wxTextCtrl(&d,-1,"",wxDefaultPosition,wxDefaultSize,0,IntValidator(c->ass->GetScriptInfoAsInt("PlayResY")));
|
||||
|
||||
wxButton *FromVideo = new wxButton(&d,-1,_("From &video"));
|
||||
if (!c->project->VideoProvider())
|
||||
|
@ -173,7 +173,7 @@ DialogProperties::DialogProperties(agi::Context *c)
|
|||
}
|
||||
|
||||
void DialogProperties::AddProperty(wxSizer *sizer, wxString const& label, std::string const& property) {
|
||||
wxTextCtrl *ctrl = new wxTextCtrl(&d, -1, to_wx(c->ass->GetScriptInfo(property)), wxDefaultPosition, wxSize(200, 20));
|
||||
wxTextCtrl *ctrl = new wxTextCtrl(&d, -1, to_wx(c->ass->GetScriptInfo(property)));
|
||||
sizer->Add(new wxStaticText(&d, -1, label), wxSizerFlags().Center().Left());
|
||||
sizer->Add(ctrl, wxSizerFlags(1).Expand());
|
||||
properties.push_back({property, ctrl});
|
||||
|
|
|
@ -112,7 +112,7 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings)
|
|||
|
||||
// Create all controls and set validators
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
margin_ctrl[i] = new wxSpinCtrl(&d, -1, "0", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, -9999, 9999, 0);
|
||||
margin_ctrl[i] = new wxSpinCtrl(&d, -1, "0", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -9999, 9999, 0);
|
||||
margin_ctrl[i]->SetValidator(wxGenericValidator(&settings.margin[i]));
|
||||
}
|
||||
|
||||
|
@ -122,12 +122,12 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings)
|
|||
margin_ctrl[RIGHT]->Enable(false);
|
||||
margin_ctrl[BOTTOM]->Enable(false);
|
||||
|
||||
source_x = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
source_y = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
source_x = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
source_y = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
source_matrix = new wxComboBox(&d, -1, "", wxDefaultPosition,
|
||||
wxDefaultSize, to_wx(MatrixNames()), wxCB_READONLY);
|
||||
dest_x = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
dest_y = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
dest_x = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
dest_y = new wxSpinCtrl(&d, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, INT_MAX);
|
||||
dest_matrix = new wxComboBox(&d, -1, "", wxDefaultPosition, wxDefaultSize,
|
||||
to_wx(MatrixNames()), wxCB_READONLY);
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
|
|||
|
||||
auto num_text_ctrl = [&](double *value, double min, double max, double step) -> wxSpinCtrlDouble * {
|
||||
auto scd = new wxSpinCtrlDouble(this, -1, "", wxDefaultPosition,
|
||||
wxSize(75, -1), wxSP_ARROW_KEYS, min, max, *value, step);
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, min, max, *value, step);
|
||||
scd->SetValidator(DoubleSpinValidator(value));
|
||||
scd->Bind(wxEVT_SPINCTRLDOUBLE, [=](wxSpinDoubleEvent &evt) {
|
||||
evt.Skip();
|
||||
|
@ -197,10 +197,12 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
|
|||
new ColourButton(this, wxSize(55, 16), true, style->outline, ColorValidator(&work->outline)),
|
||||
new ColourButton(this, wxSize(55, 16), true, style->shadow, ColorValidator(&work->shadow))
|
||||
};
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int i = 0; i < 3; i++) {
|
||||
margin[i] = new wxSpinCtrl(this, -1, std::to_wstring(style->Margin[i]),
|
||||
wxDefaultPosition, wxSize(60, -1),
|
||||
wxSP_ARROW_KEYS, 0, 9999, style->Margin[i]);
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, 0, 9999, style->Margin[i]);
|
||||
margin[i]->SetInitialSize(margin[i]->GetSizeFromTextSize(GetTextExtent(wxS("0000"))));
|
||||
}
|
||||
|
||||
Alignment = new wxRadioBox(this, -1, _("Alignment"), wxDefaultPosition, wxDefaultSize, 9, alignValues, 3, wxRA_SPECIFY_COLS);
|
||||
auto Outline = num_text_ctrl(&work->outline_w, 0.0, 1000.0, 0.1);
|
||||
|
|
|
@ -144,8 +144,8 @@ DialogTimingProcessor::DialogTimingProcessor(agi::Context *c)
|
|||
d.SetIcon(GETICON(timing_processor_toolbutton_16));
|
||||
|
||||
// Read options
|
||||
leadIn = OPT_GET("Audio/Lead/IN")->GetInt();
|
||||
leadOut = OPT_GET("Audio/Lead/OUT")->GetInt();
|
||||
leadIn = OPT_GET("Tool/Timing Post Processor/Lead/IN")->GetInt();
|
||||
leadOut = OPT_GET("Tool/Timing Post Processor/Lead/OUT")->GetInt();
|
||||
beforeStart = OPT_GET("Tool/Timing Post Processor/Threshold/Key Start Before")->GetInt();
|
||||
beforeEnd = OPT_GET("Tool/Timing Post Processor/Threshold/Key End Before")->GetInt();
|
||||
afterStart = OPT_GET("Tool/Timing Post Processor/Threshold/Key Start After")->GetInt();
|
||||
|
@ -305,8 +305,8 @@ void DialogTimingProcessor::UpdateControls() {
|
|||
void DialogTimingProcessor::OnApply(wxCommandEvent &) {
|
||||
d.TransferDataFromWindow();
|
||||
// Save settings
|
||||
OPT_SET("Audio/Lead/IN")->SetInt(leadIn);
|
||||
OPT_SET("Audio/Lead/OUT")->SetInt(leadOut);
|
||||
OPT_SET("Tool/Timing Post Processor/Lead/IN")->SetInt(leadIn);
|
||||
OPT_SET("Tool/Timing Post Processor/Lead/OUT")->SetInt(leadOut);
|
||||
OPT_SET("Tool/Timing Post Processor/Threshold/Key Start Before")->SetInt(beforeStart);
|
||||
OPT_SET("Tool/Timing Post Processor/Threshold/Key Start After")->SetInt(afterStart);
|
||||
OPT_SET("Tool/Timing Post Processor/Threshold/Key End Before")->SetInt(beforeEnd);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "format.h"
|
||||
#include "help_button.h"
|
||||
#include "libresrc/libresrc.h"
|
||||
#include "options.h"
|
||||
#include "persist_location.h"
|
||||
#include "project.h"
|
||||
#include "subs_edit_ctrl.h"
|
||||
|
@ -57,7 +58,8 @@ static void add_hotkey(wxSizer *sizer, wxWindow *parent, const char *command, wx
|
|||
|
||||
// Skip over override blocks, comments, and whitespace between blocks
|
||||
static bool bad_block(std::unique_ptr<AssDialogueBlock> &block) {
|
||||
return block->GetType() != AssBlockType::PLAIN || boost::all(block->GetText(), boost::is_space());
|
||||
bool is_whitespace = boost::all(block->GetText(), boost::is_space());
|
||||
return block->GetType() != AssBlockType::PLAIN || (is_whitespace && OPT_GET("Tool/Translation Assistant/Skip Whitespace")->GetBool());
|
||||
}
|
||||
|
||||
DialogTranslation::DialogTranslation(agi::Context *c)
|
||||
|
@ -95,7 +97,11 @@ DialogTranslation::DialogTranslation(agi::Context *c)
|
|||
translated_text->SetMarginWidth(1, 0);
|
||||
translated_text->SetFocus();
|
||||
translated_text->Bind(wxEVT_CHAR_HOOK, &DialogTranslation::OnKeyDown, this);
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
translated_text->CmdKeyAssign(wxSTC_KEY_RETURN, wxSTC_KEYMOD_SHIFT, wxSTC_CMD_NEWLINE);
|
||||
#else
|
||||
translated_text->CmdKeyAssign(wxSTC_KEY_RETURN, wxSTC_SCMOD_SHIFT, wxSTC_CMD_NEWLINE);
|
||||
#endif
|
||||
|
||||
wxSizer *translated_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Translation"));
|
||||
translated_box->Add(translated_text, 1, wxEXPAND, 0);
|
||||
|
@ -244,7 +250,11 @@ void DialogTranslation::UpdateDisplay() {
|
|||
int initial_pos = original_text->GetLength();
|
||||
original_text->AppendTextRaw(block->GetText().c_str());
|
||||
if (i == cur_block) {
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
original_text->StartStyling(initial_pos);
|
||||
#else
|
||||
original_text->StartStyling(initial_pos, 31);
|
||||
#endif
|
||||
original_text->SetStyling(block->GetText().size(), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,6 @@ bool update_video_properties(AssFile *file, const AsyncVideoProvider *new_provid
|
|||
return true;
|
||||
|
||||
case MISMATCH_RESAMPLE:
|
||||
// Fallthrough to prompt if the AR changed
|
||||
if (!ar_changed) {
|
||||
ResampleResolution(file, {
|
||||
{0, 0, 0, 0},
|
||||
|
@ -141,6 +140,8 @@ bool update_video_properties(AssFile *file, const AsyncVideoProvider *new_provid
|
|||
});
|
||||
return true;
|
||||
}
|
||||
// Fallthrough
|
||||
// to prompt if the AR changed
|
||||
|
||||
case MISMATCH_PROMPT:
|
||||
int res = prompt(parent, ar_changed, sx, sy, vx, vy);
|
||||
|
|
|
@ -74,3 +74,4 @@ void ShowSpellcheckerDialog(agi::Context *c);
|
|||
void ShowStyleManagerDialog(agi::Context *c);
|
||||
void ShowTimingProcessorDialog(agi::Context *c);
|
||||
void ShowVideoDetailsDialog(agi::Context *c);
|
||||
void ShowAlignToVideoDialog(agi::Context* c);
|
||||
|
|
9
src/dpi_aware.manifest
Normal file
9
src/dpi_aware.manifest
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
|
@ -78,9 +78,9 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent, a
|
|||
initialInput = "23.976";
|
||||
FromVideo->Enable(false);
|
||||
}
|
||||
InputFramerate = new wxTextCtrl(base,-1,initialInput,wxDefaultPosition,wxSize(60,20));
|
||||
InputSizer->Add(InputFramerate,0,wxEXPAND | wxLEFT,5);
|
||||
InputSizer->Add(FromVideo,0,wxEXPAND | wxLEFT,5);
|
||||
InputFramerate = new wxTextCtrl(base,-1,initialInput);
|
||||
InputSizer->Add(InputFramerate, 0, wxEXPAND);
|
||||
InputSizer->Add(FromVideo, 0, wxEXPAND | wxLEFT, 5);
|
||||
InputSizer->AddStretchSpacer(1);
|
||||
|
||||
// Output sizers
|
||||
|
@ -90,7 +90,7 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent, a
|
|||
|
||||
// Output top line
|
||||
RadioOutputVFR = new wxRadioButton(base,-1,_("V&ariable"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP);
|
||||
OutputSizerTop->Add(RadioOutputVFR,0,wxEXPAND,0);
|
||||
OutputSizerTop->Add(RadioOutputVFR, wxEXPAND);
|
||||
|
||||
// Output bottom line
|
||||
RadioOutputCFR = new wxRadioButton(base,-1,_("&Constant: "));
|
||||
|
@ -99,9 +99,9 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent, a
|
|||
RadioOutputVFR->Enable(false);
|
||||
RadioOutputCFR->SetValue(true);
|
||||
}
|
||||
OutputFramerate = new wxTextCtrl(base,-1,initialOutput,wxDefaultPosition,wxSize(60,20));
|
||||
OutputSizerBottom->Add(RadioOutputCFR,0,wxEXPAND,0);
|
||||
OutputSizerBottom->Add(OutputFramerate,0,wxEXPAND | wxLEFT,5);
|
||||
OutputFramerate = new wxTextCtrl(base,-1,initialOutput);
|
||||
OutputSizerBottom->Add(RadioOutputCFR, wxEXPAND);
|
||||
OutputSizerBottom->Add(OutputFramerate, 0, wxEXPAND | wxLEFT, 5);
|
||||
OutputSizerBottom->AddStretchSpacer(1);
|
||||
|
||||
// Reverse checkbox
|
||||
|
|
|
@ -67,7 +67,7 @@ enum {
|
|||
FFmpegSourceProvider::FFmpegSourceProvider(agi::BackgroundRunner *br)
|
||||
: br(br)
|
||||
{
|
||||
FFMS_Init(0, 1);
|
||||
FFMS_Init(0, 0);
|
||||
}
|
||||
|
||||
/// @brief Does indexing of a source file
|
||||
|
|
|
@ -240,8 +240,6 @@ void FrameMain::SetDisplayMode(int video, int audio) {
|
|||
TopSizer->Show(videoBox, showVideo, true);
|
||||
ToolsSizer->Show(audioBox, showAudio, true);
|
||||
|
||||
MainSizer->CalcMin();
|
||||
MainSizer->RecalcSizes();
|
||||
MainSizer->Layout();
|
||||
Layout();
|
||||
|
||||
|
|
|
@ -52,10 +52,9 @@
|
|||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
/// @class OpenGLTextGlyph
|
||||
/// @brief Struct storing the information needed to draw a glyph
|
||||
struct OpenGLTextGlyph {
|
||||
struct OpenGLText::OpenGLTextGlyph {
|
||||
wxString str; ///< String containing the glyph(s) this is for
|
||||
int tex = 0; ///< OpenGL texture to draw for this glyph
|
||||
float x1 = 0; ///< Left x coordinate of this glyph in the containing texture
|
||||
|
@ -108,7 +107,7 @@ struct OpenGLTextGlyph {
|
|||
|
||||
/// @class OpenGLTextTexture
|
||||
/// @brief OpenGL texture which stores one or more glyphs as sprites
|
||||
class OpenGLTextTexture final : boost::noncopyable {
|
||||
class OpenGLText::OpenGLTextTexture final : boost::noncopyable {
|
||||
int x = 0; ///< Next x coordinate at which a glyph can be inserted
|
||||
int y = 0; ///< Next y coordinate at which a glyph can be inserted
|
||||
int nextY = 0; ///< Y coordinate of the next line; tracked due to that lines
|
||||
|
@ -217,8 +216,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
OpenGLText::OpenGLText() { }
|
||||
OpenGLText::~OpenGLText() { }
|
||||
|
||||
|
@ -286,12 +283,12 @@ void OpenGLText::GetExtent(std::string const& text, int &w, int &h) {
|
|||
}
|
||||
}
|
||||
|
||||
OpenGLTextGlyph const& OpenGLText::GetGlyph(int i) {
|
||||
OpenGLText::OpenGLTextGlyph const& OpenGLText::GetGlyph(int i) {
|
||||
auto res = glyphs.find(i);
|
||||
return res != glyphs.end() ? res->second : CreateGlyph(i);
|
||||
}
|
||||
|
||||
OpenGLTextGlyph const& OpenGLText::CreateGlyph(int n) {
|
||||
OpenGLText::OpenGLTextGlyph const& OpenGLText::CreateGlyph(int n) {
|
||||
OpenGLTextGlyph &glyph = glyphs.emplace(n, OpenGLTextGlyph(n, font)).first->second;
|
||||
|
||||
// Insert into some texture
|
||||
|
|
|
@ -34,16 +34,13 @@
|
|||
|
||||
#include <wx/font.h>
|
||||
|
||||
namespace {
|
||||
struct OpenGLTextGlyph;
|
||||
class OpenGLTextTexture;
|
||||
}
|
||||
|
||||
namespace agi { struct Color; }
|
||||
|
||||
typedef boost::container::map<int, OpenGLTextGlyph> glyphMap;
|
||||
|
||||
class OpenGLText {
|
||||
struct OpenGLTextGlyph;
|
||||
class OpenGLTextTexture;
|
||||
typedef boost::container::map<int, OpenGLTextGlyph> glyphMap;
|
||||
|
||||
float r = 1.f, g = 1.f, b = 1.f, a = 1.f;
|
||||
|
||||
int fontSize = 0;
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
#include <wx/msgdlg.h>
|
||||
|
||||
namespace {
|
||||
const char* added_hotkeys_cj[][3] = {
|
||||
{"time/align", "Video", "KP_TAB"},
|
||||
{nullptr}
|
||||
};
|
||||
|
||||
const char *added_hotkeys_7035[][3] = {
|
||||
{"audio/play/line", "Audio", "R"},
|
||||
{nullptr}
|
||||
|
@ -47,10 +52,12 @@ namespace {
|
|||
{nullptr}
|
||||
};
|
||||
|
||||
#ifdef __WXMAC__
|
||||
const char *added_hotkeys_minimize[][3] = {
|
||||
{"app/minimize", "Default", "Ctrl-M"},
|
||||
{nullptr}
|
||||
};
|
||||
#endif
|
||||
|
||||
void migrate_hotkeys(const char *added[][3]) {
|
||||
auto hk_map = hotkey::inst->GetHotkeyMap();
|
||||
|
@ -81,6 +88,11 @@ void init() {
|
|||
|
||||
auto migrations = OPT_GET("App/Hotkey Migrations")->GetListString();
|
||||
|
||||
if (boost::find(migrations, "cj") == end(migrations)) {
|
||||
migrate_hotkeys(added_hotkeys_cj);
|
||||
migrations.emplace_back("cj");
|
||||
}
|
||||
|
||||
if (boost::find(migrations, "7035") == end(migrations)) {
|
||||
migrate_hotkeys(added_hotkeys_7035);
|
||||
migrations.emplace_back("7035");
|
||||
|
|
127
src/image_position_picker.cpp
Normal file
127
src/image_position_picker.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include "image_position_picker.h"
|
||||
BEGIN_EVENT_TABLE(ImagePositionPicker, wxPanel)
|
||||
// some useful events
|
||||
/*
|
||||
EVT_MOTION(ImagePositionPicker::mouseMoved)
|
||||
EVT_LEFT_DOWN(ImagePositionPicker::mouseDown)
|
||||
EVT_LEFT_UP(ImagePositionPicker::mouseReleased)
|
||||
EVT_RIGHT_DOWN(ImagePositionPicker::rightClick)
|
||||
EVT_LEAVE_WINDOW(ImagePositionPicker::mouseLeftWindow)
|
||||
EVT_KEY_DOWN(ImagePositionPicker::keyPressed)
|
||||
EVT_KEY_UP(ImagePositionPicker::keyReleased)
|
||||
EVT_MOUSEWHEEL(ImagePositionPicker::mouseWheelMoved)
|
||||
*/
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(ImagePositionPicker::paintEvent)
|
||||
//Size event
|
||||
EVT_SIZE(ImagePositionPicker::OnSize)
|
||||
EVT_MOUSE_EVENTS(ImagePositionPicker::OnMouseEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// some useful events
|
||||
/*
|
||||
void ImagePositionPicker::mouseMoved(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::mouseDown(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::mouseWheelMoved(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::mouseReleased(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::rightClick(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::mouseLeftWindow(wxMouseEvent& event) {}
|
||||
void ImagePositionPicker::keyPressed(wxKeyEvent& event) {}
|
||||
void ImagePositionPicker::keyReleased(wxKeyEvent& event) {}
|
||||
*/
|
||||
|
||||
ImagePositionPicker::ImagePositionPicker(wxWindow* parent, wxImage i, updator upd) : wxPanel(parent)
|
||||
{
|
||||
image = i;
|
||||
prevW = -1;
|
||||
prevH = -1;
|
||||
w = image.GetWidth();
|
||||
h = image.GetHeight();
|
||||
update = upd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the system of by wxWidgets when the panel needs
|
||||
* to be redrawn. You can also trigger this call by
|
||||
* calling Refresh()/Update().
|
||||
*/
|
||||
|
||||
void ImagePositionPicker::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Alternatively, you can use a clientDC to paint on the panel
|
||||
* at any time. Using this generally does not free you from
|
||||
* catching paint events, since it is possible that e.g. the window
|
||||
* manager throws away your drawing when the window comes to the
|
||||
* background, and expects you will redraw it when the window comes
|
||||
* back (by sending a paint event).
|
||||
*/
|
||||
void ImagePositionPicker::paintNow()
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxClientDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we do the actual rendering. I put it in a separate
|
||||
* method so that it can work no matter what type of DC
|
||||
* (e.g. wxPaintDC or wxClientDC) is used.
|
||||
*/
|
||||
void ImagePositionPicker::render(wxDC& dc)
|
||||
{
|
||||
int neww, newh;
|
||||
dc.GetSize(&neww, &newh);
|
||||
|
||||
if (neww != prevW || newh != prevH)
|
||||
{
|
||||
// keep the image proportionate
|
||||
int ww, hh;
|
||||
if (double(neww) / w >= double(newh) / h) // too long
|
||||
{
|
||||
ww = newh * w / h;
|
||||
hh = newh;
|
||||
}
|
||||
else
|
||||
{
|
||||
ww = neww;
|
||||
hh = neww * h / w;
|
||||
}
|
||||
resized = wxBitmap(image.Scale(ww, hh /*, wxIMAGE_QUALITY_HIGH*/));
|
||||
prevW = ww;
|
||||
prevH = hh;
|
||||
dc.DrawBitmap(resized, 0, 0, false);
|
||||
}
|
||||
else {
|
||||
dc.DrawBitmap(resized, 0, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we call refresh to tell the panel to draw itself again.
|
||||
* So when the user resizes the image panel the image should be resized too.
|
||||
*/
|
||||
void ImagePositionPicker::OnSize(wxSizeEvent& event) {
|
||||
Refresh();
|
||||
//skip the event.
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void ImagePositionPicker::OnMouseEvent(wxMouseEvent& evt)
|
||||
{
|
||||
wxPoint pos = evt.GetPosition();
|
||||
if (evt.Dragging() || evt.LeftDown() || evt.LeftUp())
|
||||
{
|
||||
int x = pos.x * w / prevW;
|
||||
int y = pos.y * h / prevH;
|
||||
if (x >= 0 && x < w && y >= 0 && y < h)
|
||||
update(x, y, image.GetRed(x, y), image.GetGreen(x, y), image.GetBlue(x, y));
|
||||
}
|
||||
}
|
37
src/image_position_picker.h
Normal file
37
src/image_position_picker.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <wx/wx.h>
|
||||
#include <wx/sizer.h>
|
||||
#include "gl_wrap.h"
|
||||
|
||||
typedef std::function<void(double, double, unsigned char, unsigned char, unsigned char)> updator;
|
||||
|
||||
class ImagePositionPicker : public wxPanel
|
||||
{
|
||||
wxImage image;
|
||||
wxBitmap resized;
|
||||
int prevW, prevH, w, h;
|
||||
|
||||
updator update;
|
||||
|
||||
public:
|
||||
ImagePositionPicker(wxWindow* parent, wxImage i, updator upd);
|
||||
|
||||
void paintEvent(wxPaintEvent & evt);
|
||||
void paintNow();
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnMouseEvent(wxMouseEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
|
||||
// some useful events
|
||||
/*
|
||||
void mouseMoved(wxMouseEvent& event);
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseWheelMoved(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
void rightClick(wxMouseEvent& event);
|
||||
void mouseLeftWindow(wxMouseEvent& event);
|
||||
void keyPressed(wxKeyEvent& event);
|
||||
void keyReleased(wxKeyEvent& event);
|
||||
*/
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
|
@ -31,5 +31,5 @@ public:
|
|||
InitialLineState(agi::Context *c);
|
||||
|
||||
std::string const& GetInitialText() const { return initial_text; }
|
||||
DEFINE_SIGNAL_ADDERS(InitialStateChanged, AddChangeListener);
|
||||
DEFINE_SIGNAL_ADDERS(InitialStateChanged, AddChangeListener)
|
||||
};
|
||||
|
|
|
@ -40,24 +40,24 @@
|
|||
"Display" : {
|
||||
"Draw" : {
|
||||
"Cursor Time" : true,
|
||||
"Inactive Comments" : true,
|
||||
"Inactive Comments" : false,
|
||||
"Keyframes in Dialogue Mode" : true,
|
||||
"Keyframes in Karaoke Mode" : true,
|
||||
"Seconds" : false,
|
||||
"Video Position" : false
|
||||
"Seconds" : true,
|
||||
"Video Position" : true
|
||||
},
|
||||
"Waveform Style" : 0
|
||||
},
|
||||
"Downmixer" : "ConvertToMono",
|
||||
"Drag Timing" : true,
|
||||
"Inactive Lines Display Mode" : 1,
|
||||
"Inactive Lines Display Mode" : 3,
|
||||
"Karaoke" : {
|
||||
"Font Face" : "Verdana",
|
||||
"Font Size" : 9
|
||||
},
|
||||
"Lead" : {
|
||||
"IN" : 200,
|
||||
"OUT" : 300
|
||||
"IN" : 100,
|
||||
"OUT" : 350
|
||||
},
|
||||
"Line Boundaries Thickness" : 2,
|
||||
"Link" : true,
|
||||
|
@ -75,11 +75,11 @@
|
|||
}
|
||||
},
|
||||
"Snap" : {
|
||||
"Distance" : 10,
|
||||
"Enable" : false
|
||||
"Distance" : 8,
|
||||
"Enable" : true
|
||||
},
|
||||
"Spectrum" : true,
|
||||
"Start Drag Sensitivity" : 3,
|
||||
"Start Drag Sensitivity" : 8,
|
||||
"Track Cursor" : {
|
||||
"Font Face" : ""
|
||||
},
|
||||
|
@ -266,6 +266,13 @@
|
|||
},
|
||||
"Video Dummy" : {
|
||||
"Last Colour" : "rgb(47, 163, 254)"
|
||||
},
|
||||
"Visual Tools" : {
|
||||
"Highlight Primary" : "rgb(255, 169, 40)",
|
||||
"Highlight Secondary" : "rgb(255, 253, 185)",
|
||||
"Lines Primary" : "rgb(187, 0, 0)",
|
||||
"Lines Secondary" : "rgb(106, 32, 19)",
|
||||
"Shaded Area Alpha" : 0.5
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -421,7 +428,7 @@
|
|||
},
|
||||
|
||||
"Timing" : {
|
||||
"Default Duration" : 2000
|
||||
"Default Duration" : 3000
|
||||
},
|
||||
|
||||
"Tool" : {
|
||||
|
@ -545,6 +552,10 @@
|
|||
}
|
||||
},
|
||||
"Only Selection" : false,
|
||||
"Lead" : {
|
||||
"IN" : 100,
|
||||
"OUT" : 350
|
||||
},
|
||||
"Threshold" : {
|
||||
"Adjacent Gap" : 300,
|
||||
"Adjacent Overlap" : 50,
|
||||
|
@ -559,10 +570,15 @@
|
|||
"X" : -1,
|
||||
"Y" : -1
|
||||
},
|
||||
"Maximized" : false
|
||||
"Maximized" : false,
|
||||
"Skip Whitespace" : true
|
||||
},
|
||||
"Visual" : {
|
||||
"Autohide": false
|
||||
},
|
||||
"Align to Video" : {
|
||||
"Tolerance" : 20,
|
||||
"Maximized" : true
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -584,13 +600,12 @@
|
|||
"Dummy" : {
|
||||
"FPS" : 23.975999999999999091,
|
||||
"Last" : {
|
||||
"Height" : 480,
|
||||
"Height" : 720,
|
||||
"Length" : 40000,
|
||||
"Width" : 640
|
||||
"Width" : 1280
|
||||
},
|
||||
"Pattern" : false
|
||||
},
|
||||
"Force BT.601" : true,
|
||||
"Last Script Resolution Mismatch Choice" : 2,
|
||||
"Open Audio" : true,
|
||||
"Overscan Mask" : false,
|
||||
|
|
|
@ -286,6 +286,9 @@
|
|||
],
|
||||
"video/frame/prev/large" : [
|
||||
"Alt-Left"
|
||||
],
|
||||
"time/align" : [
|
||||
"KP_TAB"
|
||||
]
|
||||
},
|
||||
"Translation Assistant" : {
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"subtitle/select/visible",
|
||||
"time/snap/scene",
|
||||
"time/frame/current",
|
||||
"time/align",
|
||||
"",
|
||||
"tool/style/manager",
|
||||
"subtitle/properties",
|
||||
|
|
|
@ -40,24 +40,24 @@
|
|||
"Display" : {
|
||||
"Draw" : {
|
||||
"Cursor Time" : true,
|
||||
"Inactive Comments" : true,
|
||||
"Inactive Comments" : false,
|
||||
"Keyframes in Dialogue Mode" : true,
|
||||
"Keyframes in Karaoke Mode" : true,
|
||||
"Seconds" : false,
|
||||
"Video Position" : false
|
||||
"Seconds" : true,
|
||||
"Video Position" : true
|
||||
},
|
||||
"Waveform Style" : 0
|
||||
},
|
||||
"Downmixer" : "ConvertToMono",
|
||||
"Drag Timing" : true,
|
||||
"Inactive Lines Display Mode" : 1,
|
||||
"Inactive Lines Display Mode" : 3,
|
||||
"Karaoke" : {
|
||||
"Font Face" : "",
|
||||
"Font Size" : 9
|
||||
},
|
||||
"Lead" : {
|
||||
"IN" : 200,
|
||||
"OUT" : 300
|
||||
"IN" : 100,
|
||||
"OUT" : 350
|
||||
},
|
||||
"Line Boundaries Thickness" : 2,
|
||||
"Link" : true,
|
||||
|
@ -75,11 +75,11 @@
|
|||
}
|
||||
},
|
||||
"Snap" : {
|
||||
"Distance" : 10,
|
||||
"Enable" : false
|
||||
"Distance" : 8,
|
||||
"Enable" : true
|
||||
},
|
||||
"Spectrum" : true,
|
||||
"Start Drag Sensitivity" : 3,
|
||||
"Start Drag Sensitivity" : 8,
|
||||
"Track Cursor" : {
|
||||
"Font Face" : ""
|
||||
},
|
||||
|
@ -266,6 +266,13 @@
|
|||
},
|
||||
"Video Dummy" : {
|
||||
"Last Colour" : "rgb(47, 163, 254)"
|
||||
},
|
||||
"Visual Tools" : {
|
||||
"Highlight Primary" : "rgb(255, 169, 40)",
|
||||
"Highlight Secondary" : "rgb(255, 253, 185)",
|
||||
"Lines Primary" : "rgb(187, 0, 0)",
|
||||
"Lines Secondary" : "rgb(106, 32, 19)",
|
||||
"Shaded Area Alpha" : 0.5
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -421,7 +428,7 @@
|
|||
},
|
||||
|
||||
"Timing" : {
|
||||
"Default Duration" : 2000
|
||||
"Default Duration" : 3000
|
||||
},
|
||||
|
||||
"Tool" : {
|
||||
|
@ -545,6 +552,10 @@
|
|||
}
|
||||
},
|
||||
"Only Selection" : false,
|
||||
"Lead" : {
|
||||
"IN" : 100,
|
||||
"OUT" : 350
|
||||
},
|
||||
"Threshold" : {
|
||||
"Adjacent Gap" : 300,
|
||||
"Adjacent Overlap" : 50,
|
||||
|
@ -559,7 +570,8 @@
|
|||
"X" : -1,
|
||||
"Y" : -1
|
||||
},
|
||||
"Maximized" : false
|
||||
"Maximized" : false,
|
||||
"Skip Whitespace" : true
|
||||
},
|
||||
"Visual" : {
|
||||
"Autohide": false
|
||||
|
@ -584,13 +596,12 @@
|
|||
"Dummy" : {
|
||||
"FPS" : 23.975999999999999091,
|
||||
"Last" : {
|
||||
"Height" : 480,
|
||||
"Height" : 720,
|
||||
"Length" : 40000,
|
||||
"Width" : 640
|
||||
"Width" : 1280
|
||||
},
|
||||
"Pattern" : false
|
||||
},
|
||||
"Force BT.601" : true,
|
||||
"Last Script Resolution Mismatch Choice" : 2,
|
||||
"Open Audio" : true,
|
||||
"Overscan Mask" : false,
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libaegisub/mru.h>
|
||||
#include <libaegisub/option.h>
|
||||
#include <libaegisub/option_value.h>
|
||||
|
|
|
@ -225,6 +225,9 @@ void Interface(wxTreebook *book, Preferences *parent) {
|
|||
p->OptionAdd(grid, _("Hide overrides symbol"), "Subtitle/Grid/Hide Overrides Char");
|
||||
p->OptionFont(grid, "Subtitle/Grid/");
|
||||
|
||||
auto tl_assistant = p->PageSizer(_("Translation Assistant"));
|
||||
p->OptionAdd(tl_assistant, _("Skip over whitespace"), "Tool/Translation Assistant/Skip Whitespace");
|
||||
|
||||
p->SetSizerAndFit(p->sizer);
|
||||
}
|
||||
|
||||
|
@ -285,6 +288,16 @@ void Interface_Colours(wxTreebook *book, Preferences *parent) {
|
|||
p->OptionAdd(grid, _("Lines"), "Colour/Subtitle Grid/Lines");
|
||||
p->OptionAdd(grid, _("CPS Error"), "Colour/Subtitle Grid/CPS Error");
|
||||
|
||||
auto visual_tools = p->PageSizer(_("Visual Typesetting Tools"));
|
||||
p->OptionAdd(visual_tools, _("Primary Lines"), "Colour/Visual Tools/Lines Primary");
|
||||
p->OptionAdd(visual_tools, _("Secondary Lines"), "Colour/Visual Tools/Lines Secondary");
|
||||
p->OptionAdd(visual_tools, _("Primary Highlight"), "Colour/Visual Tools/Highlight Primary");
|
||||
p->OptionAdd(visual_tools, _("Secondary Highlight"), "Colour/Visual Tools/Highlight Secondary");
|
||||
|
||||
// Separate sizer to prevent the colors in the visual tools section from getting resized
|
||||
auto visual_tools_alpha = p->PageSizer(_("Visual Typesetting Tools Alpha"));
|
||||
p->OptionAdd(visual_tools_alpha, _("Shaded Area"), "Colour/Visual Tools/Shaded Area Alpha", 0, 1, 0.1);
|
||||
|
||||
p->sizer = main_sizer;
|
||||
|
||||
p->SetSizerAndFit(p->sizer);
|
||||
|
@ -421,9 +434,6 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) {
|
|||
wxArrayString sp_choice = to_wx(SubtitlesProviderFactory::GetClasses());
|
||||
p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider");
|
||||
|
||||
p->CellSkip(expert);
|
||||
p->OptionAdd(expert, _("Force BT.601"), "Video/Force BT.601");
|
||||
|
||||
#ifdef WITH_AVISYNTH
|
||||
auto avisynth = p->PageSizer("Avisynth");
|
||||
p->OptionAdd(avisynth, _("Allow pre-2.56a Avisynth"), "Provider/Avisynth/Allow Ancient");
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
OPTION_UPDATER(StringUpdater, wxCommandEvent, OptionValueString, from_wx(evt.GetString()));
|
||||
OPTION_UPDATER(IntUpdater, wxSpinEvent, OptionValueInt, evt.GetInt());
|
||||
OPTION_UPDATER(IntCBUpdater, wxCommandEvent, OptionValueInt, evt.GetInt());
|
||||
OPTION_UPDATER(DoubleUpdater, wxSpinEvent, OptionValueDouble, evt.GetInt());
|
||||
OPTION_UPDATER(DoubleUpdater, wxSpinDoubleEvent, OptionValueDouble, evt.GetValue());
|
||||
OPTION_UPDATER(BoolUpdater, wxCommandEvent, OptionValueBool, !!evt.GetInt());
|
||||
OPTION_UPDATER(ColourUpdater, ValueEvent<agi::Color>, OptionValueColor, evt.Get());
|
||||
|
||||
|
@ -132,7 +132,7 @@ wxControl *OptionPage::OptionAdd(wxFlexGridSizer *flex, const wxString &name, co
|
|||
|
||||
case agi::OptionType::Double: {
|
||||
auto scd = new wxSpinCtrlDouble(this, -1, std::to_wstring(opt->GetDouble()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, min, max, opt->GetDouble(), inc);
|
||||
scd->Bind(wxEVT_SPINCTRL, DoubleUpdater(opt_name, parent));
|
||||
scd->Bind(wxEVT_SPINCTRLDOUBLE, DoubleUpdater(opt_name, parent));
|
||||
Add(flex, name, scd);
|
||||
return scd;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ Project::Project(agi::Context *c) : context(c) {
|
|||
OPT_SUB("Provider/Video/FFmpegSource/Decoding Threads", &Project::ReloadVideo, this);
|
||||
OPT_SUB("Provider/Video/FFmpegSource/Unsafe Seeking", &Project::ReloadVideo, this);
|
||||
OPT_SUB("Subtitle/Provider", &Project::ReloadVideo, this);
|
||||
OPT_SUB("Video/Force BT.601", &Project::ReloadVideo, this);
|
||||
OPT_SUB("Video/Provider", &Project::ReloadVideo, this);
|
||||
}
|
||||
|
||||
|
@ -506,6 +505,9 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
|
|||
subs.clear();
|
||||
}
|
||||
|
||||
if (!audio.empty())
|
||||
DoLoadAudio(audio, false);
|
||||
|
||||
if (!video.empty() && DoLoadVideo(video)) {
|
||||
double dar = video_provider->GetDAR();
|
||||
if (dar > 0)
|
||||
|
@ -521,12 +523,11 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
|
|||
LoadTimecodes(timecodes);
|
||||
if (!keyframes.empty())
|
||||
LoadKeyframes(keyframes);
|
||||
}
|
||||
|
||||
if (!audio.empty())
|
||||
DoLoadAudio(audio, false);
|
||||
else if (OPT_GET("Video/Open Audio")->GetBool() && audio_file != video_file)
|
||||
DoLoadAudio(video_file, true);
|
||||
// Load audio from video
|
||||
if (audio.empty() && OPT_GET("Video/Open Audio")->GetBool() && audio_file != video_file)
|
||||
DoLoadAudio(video_file, true);
|
||||
}
|
||||
|
||||
if (!subs.empty())
|
||||
LoadUnloadFiles(properties);
|
||||
|
|
|
@ -48,7 +48,7 @@ static const std::string names[] = {
|
|||
};
|
||||
|
||||
YCbCrMatrix MatrixFromString(std::string const& str) {
|
||||
if (str.empty()) return YCbCrMatrix::tv_601;
|
||||
if (str.empty()) return YCbCrMatrix::tv_709;
|
||||
auto pos = std::find(std::begin(names), std::end(names), str);
|
||||
if (pos == std::end(names))
|
||||
return YCbCrMatrix::rgb;
|
||||
|
@ -233,6 +233,7 @@ void ResampleResolution(AssFile *ass, ResampleSettings settings) {
|
|||
switch (settings.ar_mode) {
|
||||
case ResampleARMode::RemoveBorder:
|
||||
border_horizontally = !border_horizontally;
|
||||
// fallthrough
|
||||
case ResampleARMode::AddBorder:
|
||||
if (border_horizontally) // Wider/Shorter
|
||||
settings.margin[LEFT] = settings.margin[RIGHT] = (settings.source_y * new_ar - settings.source_x) / 2;
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
#include <libaegisub/make_unique.h>
|
||||
#include <libaegisub/spellchecker.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
namespace agi {
|
||||
class OptionValue;
|
||||
std::unique_ptr<agi::SpellChecker> CreateCocoaSpellChecker(OptionValue *opt);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<agi::SpellChecker> SpellCheckerFactory::GetSpellChecker() {
|
||||
#ifdef __APPLE__
|
||||
|
|
|
@ -122,8 +122,7 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
|
|||
|
||||
style_box = MakeComboBox("Default", wxCB_READONLY, &SubsEditBox::OnStyleChange, _("Style for this line"));
|
||||
|
||||
style_edit_button = new wxButton(this, -1, _("Edit"), wxDefaultPosition,
|
||||
wxSize(GetTextExtent(_("Edit")).GetWidth() + 20, -1));
|
||||
style_edit_button = new wxButton(this, -1, _("Edit"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
style_edit_button->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) {
|
||||
if (active_style) {
|
||||
wxArrayString font_list = wxFontEnumerator::GetFacenames();
|
||||
|
@ -133,24 +132,26 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
|
|||
});
|
||||
top_sizer->Add(style_edit_button, wxSizerFlags().Center().Border(wxRIGHT));
|
||||
|
||||
actor_box = new Placeholder<wxComboBox>(this, _("Actor"), wxSize(110, -1), wxCB_DROPDOWN | wxTE_PROCESS_ENTER, _("Actor name for this speech. This is only for reference, and is mainly useless."));
|
||||
actor_box = new Placeholder<wxComboBox>(this, _("Actor"), wxDefaultSize, wxCB_DROPDOWN | wxTE_PROCESS_ENTER, _("Actor name for this speech. This is only for reference, and is mainly useless."));
|
||||
Bind(wxEVT_TEXT, &SubsEditBox::OnActorChange, this, actor_box->GetId());
|
||||
Bind(wxEVT_COMBOBOX, &SubsEditBox::OnActorChange, this, actor_box->GetId());
|
||||
top_sizer->Add(actor_box, wxSizerFlags(2).Center().Border(wxRIGHT));
|
||||
|
||||
effect_box = new Placeholder<wxComboBox>(this, _("Effect"), wxSize(80,-1), wxCB_DROPDOWN | wxTE_PROCESS_ENTER, _("Effect for this line. This can be used to store extra information for karaoke scripts, or for the effects supported by the renderer."));
|
||||
effect_box = new Placeholder<wxComboBox>(this, _("Effect"), wxDefaultSize, wxCB_DROPDOWN | wxTE_PROCESS_ENTER, _("Effect for this line. This can be used to store extra information for karaoke scripts, or for the effects supported by the renderer."));
|
||||
Bind(wxEVT_TEXT, &SubsEditBox::OnEffectChange, this, effect_box->GetId());
|
||||
Bind(wxEVT_COMBOBOX, &SubsEditBox::OnEffectChange, this, effect_box->GetId());
|
||||
top_sizer->Add(effect_box, 3, wxALIGN_CENTER, 5);
|
||||
|
||||
char_count = new wxTextCtrl(this, -1, "0", wxDefaultPosition, wxSize(30, -1), wxTE_READONLY | wxTE_CENTER);
|
||||
char_count = new wxTextCtrl(this, -1, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_CENTER);
|
||||
char_count->SetInitialSize(char_count->GetSizeFromTextSize(GetTextExtent(wxS("000"))));
|
||||
char_count->SetToolTip(_("Number of characters in the longest line of this subtitle."));
|
||||
top_sizer->Add(char_count, 0, wxALIGN_CENTER, 5);
|
||||
|
||||
// Middle controls
|
||||
middle_left_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
layer = new wxSpinCtrl(this,-1,"",wxDefaultPosition,wxSize(50,-1), wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,0,0x7FFFFFFF,0);
|
||||
layer = new wxSpinCtrl(this,-1,"",wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,0,0x7FFFFFFF,0);
|
||||
layer->SetInitialSize(layer->GetSizeFromTextSize(GetTextExtent(wxS("0"))));
|
||||
layer->SetToolTip(_("Layer number"));
|
||||
middle_left_sizer->Add(layer, wxSizerFlags().Center());
|
||||
middle_left_sizer->AddSpacer(5);
|
||||
|
@ -198,10 +199,15 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
|
|||
main_sizer->Add(middle_right_sizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
||||
|
||||
// Text editor
|
||||
edit_ctrl = new SubsTextEditCtrl(this, wxSize(300,50), wxBORDER_SUNKEN, c);
|
||||
edit_ctrl = new SubsTextEditCtrl(this, wxDefaultSize, wxBORDER_SUNKEN, c);
|
||||
edit_ctrl->Bind(wxEVT_CHAR_HOOK, &SubsEditBox::OnKeyDown, this);
|
||||
|
||||
secondary_editor = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(300,50), wxBORDER_SUNKEN | wxTE_MULTILINE | wxTE_READONLY);
|
||||
secondary_editor = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN | wxTE_MULTILINE | wxTE_READONLY);
|
||||
// Here we use the height of secondary_editor as the initial size of edit_ctrl,
|
||||
// which is more reasonable than the default given by wxWidgets.
|
||||
// See: https://trac.wxwidgets.org/ticket/18471#ticket
|
||||
// https://github.com/wangqr/Aegisub/issues/4
|
||||
edit_ctrl->SetInitialSize(secondary_editor->GetSize());
|
||||
|
||||
main_sizer->Add(secondary_editor,1,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
||||
main_sizer->Add(edit_ctrl,1,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
||||
|
@ -248,7 +254,8 @@ SubsEditBox::~SubsEditBox() {
|
|||
}
|
||||
|
||||
wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, int margin, wxString const& commit_msg) {
|
||||
wxTextCtrl *ctrl = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(40,-1), wxTE_CENTRE | wxTE_PROCESS_ENTER, IntValidator());
|
||||
wxTextCtrl *ctrl = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxDefaultSize, wxTE_CENTRE | wxTE_PROCESS_ENTER, IntValidator());
|
||||
ctrl->SetInitialSize(ctrl->GetSizeFromTextSize(GetTextExtent(wxS("0000"))));
|
||||
ctrl->SetMaxLength(4);
|
||||
ctrl->SetToolTip(tooltip);
|
||||
middle_left_sizer->Add(ctrl, wxSizerFlags().Center());
|
||||
|
@ -263,7 +270,8 @@ wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, int margin, wxS
|
|||
}
|
||||
|
||||
TimeEdit *SubsEditBox::MakeTimeCtrl(wxString const& tooltip, TimeField field) {
|
||||
TimeEdit *ctrl = new TimeEdit(this, -1, c, "", wxSize(GetTextExtent(wxS(" 0:00:00.000 ")).GetWidth(),-1), field == TIME_END);
|
||||
TimeEdit *ctrl = new TimeEdit(this, -1, c, "", wxDefaultSize, field == TIME_END);
|
||||
ctrl->SetInitialSize(ctrl->GetSizeFromTextSize(GetTextExtent(wxS("0:00:00.000"))));
|
||||
ctrl->SetToolTip(tooltip);
|
||||
Bind(wxEVT_TEXT, [=](wxCommandEvent&) { CommitTimes(field); }, ctrl->GetId());
|
||||
ctrl->Bind(wxEVT_CHAR_HOOK, time_edit_char_hook);
|
||||
|
@ -273,7 +281,7 @@ TimeEdit *SubsEditBox::MakeTimeCtrl(wxString const& tooltip, TimeField field) {
|
|||
|
||||
void SubsEditBox::MakeButton(const char *cmd_name) {
|
||||
cmd::Command *command = cmd::get(cmd_name);
|
||||
wxBitmapButton *btn = new wxBitmapButton(this, -1, command->Icon(16));
|
||||
wxBitmapButton *btn = new wxBitmapButton(this, -1, command->Icon(OPT_GET("App/Toolbar Icon Size")->GetInt()));
|
||||
ToolTipManager::Bind(btn, command->StrHelp(), "Subtitle Edit Box", cmd_name);
|
||||
|
||||
middle_right_sizer->Add(btn, wxSizerFlags().Expand());
|
||||
|
@ -291,7 +299,7 @@ wxButton *SubsEditBox::MakeBottomButton(const char *cmd_name) {
|
|||
|
||||
wxComboBox *SubsEditBox::MakeComboBox(wxString const& initial_text, int style, void (SubsEditBox::*handler)(wxCommandEvent&), wxString const& tooltip) {
|
||||
wxString styles[] = { "Default" };
|
||||
wxComboBox *ctrl = new wxComboBox(this, -1, initial_text, wxDefaultPosition, wxSize(110,-1), 1, styles, style | wxTE_PROCESS_ENTER);
|
||||
wxComboBox *ctrl = new wxComboBox(this, -1, initial_text, wxDefaultPosition, wxDefaultSize, 1, styles, style | wxTE_PROCESS_ENTER);
|
||||
ctrl->SetToolTip(tooltip);
|
||||
top_sizer->Add(ctrl, wxSizerFlags(2).Center().Border(wxRIGHT));
|
||||
Bind(wxEVT_COMBOBOX, handler, this, ctrl->GetId());
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
#include <wx/menu.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
// Maximum number of languages (locales)
|
||||
// It should be above 100 (at least 242) and probably not more than 1000
|
||||
#define LANGS_MAX 1000
|
||||
|
||||
/// Event ids
|
||||
enum {
|
||||
EDIT_MENU_SPLIT_PRESERVE = 1400,
|
||||
|
@ -73,7 +77,7 @@ enum {
|
|||
EDIT_MENU_THESAURUS_SUGS,
|
||||
EDIT_MENU_DIC_LANGUAGE = 1600,
|
||||
EDIT_MENU_DIC_LANGS,
|
||||
EDIT_MENU_THES_LANGUAGE = 1700,
|
||||
EDIT_MENU_THES_LANGUAGE = EDIT_MENU_DIC_LANGUAGE + LANGS_MAX,
|
||||
EDIT_MENU_THES_LANGS
|
||||
};
|
||||
|
||||
|
@ -88,10 +92,27 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, a
|
|||
// Set properties
|
||||
SetWrapMode(wxSTC_WRAP_WORD);
|
||||
SetMarginWidth(1,0);
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
UsePopUp(wxSTC_POPUP_NEVER);
|
||||
#else
|
||||
UsePopUp(false);
|
||||
#endif
|
||||
SetStyles();
|
||||
|
||||
// Set hotkeys
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
CmdKeyClear(wxSTC_KEY_RETURN, wxSTC_KEYMOD_CTRL);
|
||||
CmdKeyClear(wxSTC_KEY_RETURN, wxSTC_KEYMOD_SHIFT);
|
||||
CmdKeyClear(wxSTC_KEY_RETURN, wxSTC_KEYMOD_NORM);
|
||||
CmdKeyClear(wxSTC_KEY_TAB, wxSTC_KEYMOD_NORM);
|
||||
CmdKeyClear(wxSTC_KEY_TAB, wxSTC_KEYMOD_SHIFT);
|
||||
CmdKeyClear('D', wxSTC_KEYMOD_CTRL);
|
||||
CmdKeyClear('L', wxSTC_KEYMOD_CTRL);
|
||||
CmdKeyClear('L', wxSTC_KEYMOD_CTRL | wxSTC_KEYMOD_SHIFT);
|
||||
CmdKeyClear('T', wxSTC_KEYMOD_CTRL);
|
||||
CmdKeyClear('T', wxSTC_KEYMOD_CTRL | wxSTC_KEYMOD_SHIFT);
|
||||
CmdKeyClear('U', wxSTC_KEYMOD_CTRL);
|
||||
#else
|
||||
CmdKeyClear(wxSTC_KEY_RETURN,wxSTC_SCMOD_CTRL);
|
||||
CmdKeyClear(wxSTC_KEY_RETURN,wxSTC_SCMOD_SHIFT);
|
||||
CmdKeyClear(wxSTC_KEY_RETURN,wxSTC_SCMOD_NORM);
|
||||
|
@ -103,6 +124,7 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, a
|
|||
CmdKeyClear('T',wxSTC_SCMOD_CTRL);
|
||||
CmdKeyClear('T',wxSTC_SCMOD_CTRL | wxSTC_SCMOD_SHIFT);
|
||||
CmdKeyClear('U',wxSTC_SCMOD_CTRL);
|
||||
#endif
|
||||
|
||||
using std::bind;
|
||||
|
||||
|
@ -178,7 +200,7 @@ BEGIN_EVENT_TABLE(SubsTextEditCtrl,wxStyledTextCtrl)
|
|||
EVT_MENU_RANGE(EDIT_MENU_SUGGESTIONS,EDIT_MENU_THESAURUS-1,SubsTextEditCtrl::OnUseSuggestion)
|
||||
EVT_MENU_RANGE(EDIT_MENU_THESAURUS_SUGS,EDIT_MENU_DIC_LANGUAGE-1,SubsTextEditCtrl::OnUseSuggestion)
|
||||
EVT_MENU_RANGE(EDIT_MENU_DIC_LANGS,EDIT_MENU_THES_LANGUAGE-1,SubsTextEditCtrl::OnSetDicLanguage)
|
||||
EVT_MENU_RANGE(EDIT_MENU_THES_LANGS,EDIT_MENU_THES_LANGS+100,SubsTextEditCtrl::OnSetThesLanguage)
|
||||
EVT_MENU_RANGE(EDIT_MENU_THES_LANGS,EDIT_MENU_THES_LANGS+LANGS_MAX,SubsTextEditCtrl::OnSetThesLanguage)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
void SubsTextEditCtrl::OnLoseFocus(wxFocusEvent &event) {
|
||||
|
@ -261,7 +283,11 @@ void SubsTextEditCtrl::UpdateStyle() {
|
|||
cursor_pos = -1;
|
||||
UpdateCallTip();
|
||||
|
||||
#if wxCHECK_VERSION (3, 1, 0)
|
||||
StartStyling(0);
|
||||
#else
|
||||
StartStyling(0,255);
|
||||
#endif
|
||||
|
||||
if (!OPT_GET("Subtitle/Highlight/Syntax")->GetBool()) {
|
||||
SetStyling(line_text.size(), 0);
|
||||
|
@ -366,15 +392,16 @@ void SubsTextEditCtrl::OnContextMenu(wxContextMenuEvent &event) {
|
|||
currentWord = line_text.substr(currentWordPos.first, currentWordPos.second);
|
||||
|
||||
wxMenu menu;
|
||||
if (spellchecker)
|
||||
if (spellchecker) {
|
||||
AddSpellCheckerEntries(menu);
|
||||
|
||||
// Append language list
|
||||
menu.Append(-1,_("Spell checker language"), GetLanguagesMenu(
|
||||
EDIT_MENU_DIC_LANGS,
|
||||
to_wx(OPT_GET("Tool/Spell Checker/Language")->GetString()),
|
||||
to_wx(spellchecker->GetLanguageList())));
|
||||
menu.AppendSeparator();
|
||||
// Append language list
|
||||
menu.Append(-1, _("Spell checker language"), GetLanguagesMenu(
|
||||
EDIT_MENU_DIC_LANGS,
|
||||
to_wx(OPT_GET("Tool/Spell Checker/Language")->GetString()),
|
||||
to_wx(spellchecker->GetLanguageList())));
|
||||
menu.AppendSeparator();
|
||||
}
|
||||
|
||||
AddThesaurusEntries(menu);
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ public:
|
|||
|
||||
std::string WriteSRTTime(agi::Time const& ts)
|
||||
{
|
||||
return agi::format("%02d:%02d:%02d,%03d", ts.GetTimeHours(), ts.GetTimeMinutes(), ts.GetTimeSeconds(), ts.GetTimeMiliseconds());
|
||||
return ts.GetSrtFormatted();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst, double time) {
|
|||
csri_frame frame;
|
||||
if (dst.flipped) {
|
||||
frame.planes[0] = dst.data.data() + (dst.height-1) * dst.width * 4;
|
||||
frame.strides[0] = -(signed)dst.width * 4;
|
||||
frame.strides[0] = -(ptrdiff_t)dst.width * 4;
|
||||
}
|
||||
else {
|
||||
frame.planes[0] = dst.data.data();
|
||||
|
@ -100,7 +100,7 @@ void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst, double time) {
|
|||
}
|
||||
frame.pixfmt = CSRI_F_BGR_;
|
||||
|
||||
csri_fmt format = { frame.pixfmt, dst.width, dst.height };
|
||||
csri_fmt format = { frame.pixfmt, (unsigned)dst.width, (unsigned)dst.height };
|
||||
|
||||
std::lock_guard<std::mutex> lock(csri_mutex);
|
||||
if (!csri_request_fmt(instance.get(), &format))
|
||||
|
|
|
@ -46,7 +46,11 @@
|
|||
#include <libaegisub/util.h>
|
||||
|
||||
#include <atomic>
|
||||
#if BOOST_VERSION >= 106900
|
||||
#include <boost/gil.hpp>
|
||||
#else
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
|
|
|
@ -214,9 +214,15 @@ void AddFullScreenButton(wxWindow *) { }
|
|||
void SetFloatOnParent(wxWindow *) { }
|
||||
|
||||
// OS X implementation in retina_helper.mm
|
||||
RetinaHelper::RetinaHelper(wxWindow *) { }
|
||||
RetinaHelper::RetinaHelper(wxWindow* w) { window = w; }
|
||||
RetinaHelper::~RetinaHelper() { }
|
||||
int RetinaHelper::GetScaleFactor() const { return 1; }
|
||||
int RetinaHelper::GetScaleFactor() const {
|
||||
#ifdef __WXGTK__
|
||||
return int(window->GetContentScaleFactor());
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// OS X implementation in scintilla_ime.mm
|
||||
namespace osx { namespace ime {
|
||||
|
@ -275,7 +281,7 @@ wxString LocalizedLanguageName(wxString const& lang) {
|
|||
icu::UnicodeString ustr;
|
||||
iculoc.getDisplayName(iculoc, ustr);
|
||||
#ifdef _MSC_VER
|
||||
return wxString(ustr.getBuffer());
|
||||
return wxString((const wchar_t*)ustr.getBuffer());
|
||||
#else
|
||||
std::string utf8;
|
||||
ustr.toUTF8String(utf8);
|
||||
|
|
|
@ -47,7 +47,8 @@ IntValidator::IntValidator(int val, bool allow_negative)
|
|||
}
|
||||
|
||||
IntValidator::IntValidator(IntValidator const& rgt)
|
||||
: value(rgt.value)
|
||||
: wxValidator(rgt)
|
||||
, value(rgt.value)
|
||||
, allow_negative(rgt.allow_negative)
|
||||
{
|
||||
SetWindow(rgt.GetWindow());
|
||||
|
@ -96,7 +97,8 @@ DoubleValidator::DoubleValidator(double *val, double min, double max)
|
|||
}
|
||||
|
||||
DoubleValidator::DoubleValidator(DoubleValidator const& rgt)
|
||||
: value(rgt.value)
|
||||
: wxValidator(rgt)
|
||||
, value(rgt.value)
|
||||
, min(rgt.min)
|
||||
, max(rgt.max)
|
||||
, decimal_sep(rgt.decimal_sep)
|
||||
|
|
|
@ -58,10 +58,10 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, agi::Context *context)
|
|||
|
||||
auto mainToolbar = toolbar::GetToolbar(this, "video", context, "Video", false);
|
||||
|
||||
VideoPosition = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(110, 20), wxTE_READONLY);
|
||||
VideoPosition = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(110, -1), wxTE_READONLY);
|
||||
VideoPosition->SetToolTip(_("Current frame time and number"));
|
||||
|
||||
VideoSubsPos = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(110, 20), wxTE_READONLY);
|
||||
VideoSubsPos = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(110, -1), wxTE_READONLY);
|
||||
VideoSubsPos->SetToolTip(_("Time of this frame relative to start and end of current subs"));
|
||||
|
||||
wxArrayString choices;
|
||||
|
@ -70,7 +70,7 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, agi::Context *context)
|
|||
auto zoomBox = new wxComboBox(this, -1, "75%", wxDefaultPosition, wxDefaultSize, choices, wxCB_DROPDOWN | wxTE_PROCESS_ENTER);
|
||||
|
||||
auto visualToolBar = toolbar::GetToolbar(this, "visual_tools", context, "Video", true);
|
||||
auto visualSubToolBar = new wxToolBar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_VERTICAL | wxTB_BOTTOM | wxTB_FLAT);
|
||||
auto visualSubToolBar = new wxToolBar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_VERTICAL | wxTB_BOTTOM | wxTB_NODIVIDER | wxTB_FLAT);
|
||||
|
||||
auto videoDisplay = new VideoDisplay(visualSubToolBar, isDetached, zoomBox, this, context);
|
||||
videoDisplay->MoveBeforeInTabOrder(videoSlider);
|
||||
|
|
|
@ -410,6 +410,7 @@ void VideoDisplay::SetZoomFromBoxText(wxCommandEvent &) {
|
|||
|
||||
void VideoDisplay::SetTool(std::unique_ptr<VisualToolBase> new_tool) {
|
||||
toolBar->ClearTools();
|
||||
toolBar->AddSeparator();
|
||||
toolBar->Realize();
|
||||
toolBar->Show(false);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue