Compare commits

...

62 commits

Author SHA1 Message Date
wangqr
6702556776 Use system luajit
And drop luabins from preloaded modules
2019-09-07 22:07:22 -04:00
wangqr
bf28e7efc3 Add PulseAudio to cmake 2019-09-07 12:35:27 -04:00
wangqr
c2c44f1ad2 Fix build warnings
For pimpl with anonymous namespace, see https://stackoverflow.com/questions/39684438
2019-09-07 01:31:16 -04:00
wangqr
5dd201bc2d Update README.md and prepare for release 2019-09-05 22:16:58 -04:00
wangqr
3663d118b6 Separate desktop template for CMake
So it does not affect the translation
2019-09-04 22:46:29 -04:00
wangqr
60a722db31 Don't internally reset the selection after collected fonts
This creates an inconsistency between UI and internal mode.

Fix wangqr/Aegisub#10
2019-09-03 11:58:20 -04:00
wangqr
d65643ddee Remove extra semicolon 2019-09-02 22:23:19 -04:00
wangqr
fbca222295 Add back original travis tests 2019-09-02 22:06:41 -04:00
wangqr
3225ae39f4 Fix Makefile build
A missing header (acconf.h) issue was introduced in 34575a9786
In 419386aadd, some new source files have been added but not added to the file list in Makefile
2019-09-02 13:46:50 -04:00
wangqr
888be0607f visualSubToolBar now use same style as other toolbars
Previously visualSubToolBar has boarder while visualToolBar does not. So the width of the toolbar will change when toggling visualSubToolBar.

Now we remove the boarder so they have the same width. A separator is added at the top of visualToolBar instead to provide visual cue.

Fix wangqr/Aegisub#11
2019-09-01 22:55:13 -04:00
scx
4200b85fb4 Fix crashing when picking language
Aegisub crashes immediately after selecting any language
from the end of the list (above the 100th position).
This is because it can support no more than 100 languages.
This patch extends this limit up to 1000 languages (locales).

Fixes Aegisub/Aegisub#131
2019-09-01 19:17:35 -04:00
wangqr
0b8b286767 Fix crash on right click due to no spell checker 2019-09-01 19:15:28 -04:00
wangqr
139132a964 Use AviSynth from system 2019-09-01 19:15:21 -04:00
wangqr
4a3689d6e7 Remove the trailing period in help text of time/align
Fix wangqr/Aegisub#7
2019-08-24 02:10:08 -04:00
wangqr
248e69a9b6 Use absolute distance when scrolling audio box with mouse wheel
Instead of 1/3 screen per tick. So the distance of scroll no longer depends on the width of the audio box. Besides, 1/3 is feels to far for me when the audio box is wide.

See wangqr/Aegisub#5
2019-08-24 01:16:18 -04:00
wangqr
46474e0319 Set the height of sub box to the same as secondary_editor
The secondary_editor is a wxTextCtrl, whose height is calculated from 2 rows of text. Using this height gives better consistency on screens with different DPIs, instead of using hard coded value like 50px
2019-08-24 01:12:16 -04:00
wangqr
50544cf749 Set the height of sub box back to 50px
Revert the change made in ad15c53fb1.
As a temporary solution for wangqr/Aegisub#4.
2019-08-18 22:25:50 -04:00
wangqr
e9a68f22b9 Remove the usage of dummy wxTimerEvent 2019-07-24 09:11:17 -04:00
wangqr
d6ddea0f65 Detect EBML magic number to skip encoding detection for MKV
MKV loads slow after f733297499
2019-06-16 19:16:31 -04:00
wangqr
2bbed6c5a0 Load audio when video is successfully loaded
Fix bug introduced in 8f40ca44ce
2019-06-06 16:32:26 -04:00
wangqr
592250eeaa Remove call to wxSizer::CalcMin and wxSizer::RecalcSizes
As they are used internally by Layout and should not be called
directly.
2019-06-06 15:24:40 -04:00
wangqr
8f40ca44ce Try auto loading audio from video only when actually loading a video
If the user drop some files into Aegisub, we try to load sub, video,
audio, etc from them. When "Automatically open audio when opening
video" is checked in config, we try to load audio from the path of
the video. This should only be done if the video is newly loaded. So
we should never try to load audio from video if the user is just
opening a subtitle.

See https://github.com/Aegisub/Aegisub/issues/121#issuecomment-498489847
2019-06-06 14:31:07 -04:00
wangqr
f776db2d2b Change the default fontsize and the list of resolutions
The default fontsize is changed to 48. While it still looks small
on the default 720p video, it is actually bigger than
    20 / 480 * 720 = 30

Here 720p is the default video resolution after 837d5a41d7. Some
common resolutions are also added to the preset list.

Fix wangqr/Aegisub#3
2019-06-03 22:08:11 -04:00
wangqr
f9ffc46bf6 Add linux desktop icon 2019-05-22 20:45:51 -04:00
wangqr
019e68147e Fix FFT first sample location
Fix wangqr/Aegisub#1
2019-05-22 20:10:09 -04:00
wangqr
f733297499 Rewrite encoding detection
Now feeds all data to uchardet, when uchardet is available. The file
size limit is removed.

When uchardet is not available, we look for UTF-8 BOM.
This should make loading UTF-8-BOM files faster.
Because Aegisub always save file in UTF-8-BOM, this should also
guarentee Aegisub will load large (>100MB) file saved by itself.

See Aegisub/Aegisub#110
2019-05-18 22:13:26 -04:00
wangqr
4c6d370d51 Add install target 2019-05-18 20:10:18 -04:00
wangqr
b7c640d061 Fix High DPI issue on GTK
* Use icon size in the config
2019-05-17 13:58:14 -04:00
wangqr
2c06f03f5b Add AviSynth support 2019-05-16 11:07:57 -04:00
wangqr
1819fc8d8b Fix iconv ConversionFailure on long path 2019-05-16 11:04:53 -04:00
wangqr
ba54e8d12f Fix build warnings 2019-05-11 21:36:34 -04:00
Ryan Lucia
c76e410d30 Divorce stored TPP lead-in/out values from config
There's no real reason to link these as far as I can tell, and plenty of
valid reasons not to
2019-05-11 20:04:29 -04:00
Ryan Lucia
bb2cfb1fcd Properly ignore ASS whitespace characters in character counter 2019-05-11 20:00:49 -04:00
Ryan Lucia
9abcc03202 Add configuration options for colors in visual typesetting tools 2019-05-11 19:43:54 -04:00
Ryan Lucia
837d5a41d7 Update default config to modern standards 2019-05-11 19:38:10 -04:00
Ryan Lucia
875456c803 Use FFMS2 constant in place of magic number 2019-05-10 15:22:26 -04:00
Ryan Lucia
9ddecfdd46 Ignore VS build files
Most files were moved to .vs directory with VS15
2019-05-10 15:17:19 -04:00
Ryan Lucia
70f27eae4b Pass 0 to FFMS_Init
The argument is no longer used, and the docs specify to pass a value of 0 to avoid confusion
2019-05-10 15:12:55 -04:00
Ryan Lucia
8d2ef3fca7 Point users at a functional bug tracker 2019-05-10 15:09:25 -04:00
Ryan Lucia
48869ae0ad Fix line order when splitting after current frame 2019-05-10 15:09:05 -04:00
Ryan Lucia
b00285cf71 Use proper event for DoubleUpdater
Previously changes weren't recognized because the event bound was for integers
2019-05-10 15:06:01 -04:00
Ryan Lucia
c6c9e05406 Remove dead forums link 2019-05-10 15:05:18 -04:00
Ryan Lucia
fc1a78aeca Make translation assistant skipping whitespace an explicit setting 2019-05-10 15:04:48 -04:00
Ryan Lucia
38bb1790ab Remove Force BT.601 option and update color matrix guessing 2019-05-10 15:03:20 -04:00
Ryan Lucia
fff08c4650 Add support for setting status bar text from Lua 2019-05-10 14:54:05 -04:00
wangqr
163d57d6a2 Fix LuaJIT segfault 2019-05-09 21:36:11 -04:00
wangqr
6266867586 Fix errors in AlignToVideo
* Call TimeAtFrame with correct parameter
* Fix syntax error
2019-05-09 16:54:20 -04:00
wangqr
4431f678ce Update about dialog 2019-05-09 16:30:38 -04:00
Charlie Jiang
419386aadd Merge remote-tracking branch 'origind-dev/master'
Add align to video function
2019-05-09 16:26:08 -04:00
wangqr
c4cce28766 Update README to use CMake 2019-05-08 22:49:53 -04:00
wangqr
1ae2f60b9a Fix CMake build errors 2019-05-08 17:09:29 -04:00
wangqr
b6eebcd7ef Fix build warnings 2019-05-08 17:09:07 -04:00
wangqr
bf55264e6d Fix VS2019 compile issues 2019-05-08 16:34:53 -04:00
wangqr
34575a9786 Migrate to CMake to update packages easier 2019-05-08 16:34:39 -04:00
wangqr
69310d40ae Correctly handle memory free using Lua GC
Instead of manually free. Otherwise return value of `search' may refer to invalid memory.
Fix Aegisub/Aegisub#99
2019-03-15 00:01:29 -04:00
wangqr
657d9d5149 Bump boost version to 1.69.0
Fix Aegisub/Aegisub#93
2019-03-14 23:58:28 -04:00
wangqr
043a45cf91 Add DPI aware to Aegisub manifest 2018-12-08 01:20:08 -05:00
wangqr
ad15c53fb1 Add DPI awareness
* Removed most hard coded wxSize
* Sub edit box now have DPI aware icons
2018-12-08 01:20:08 -05:00
wangqr
841a35a6fd Fix overflow bound 2018-12-08 01:20:08 -05:00
wangqr
ee7dc6af4e Fix millisecond to centisecond convertion
Fix Aegisub/Aegisub#94
2018-12-08 01:20:08 -05:00
wangqr
77da2436c5 Change some text box size to make it looks better on HiDPI 2018-12-08 01:20:08 -05:00
wangqr
7be2325629 Fix travis-ci build script 2018-12-08 00:48:00 -05:00
117 changed files with 2199 additions and 1175 deletions

3
.gitignore vendored
View file

@ -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

View file

@ -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
View 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)

View file

@ -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.

View file

@ -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) ->

View file

@ -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
---

View file

@ -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
View 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
View 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
View 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
View 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
View 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)

View 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
View 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
View 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
)

View file

@ -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))

View file

@ -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);

View file

@ -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;
}

View file

@ -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'))

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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): ");

View file

@ -1,5 +1,5 @@
#ifdef __cplusplus
#ifndef _WIN32
#if !defined(_WIN32) && !defined(CMAKE_BUILD)
#include "../acconf.h"
#endif

View file

@ -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);

View file

@ -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},

View 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

View file

@ -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

View file

@ -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 \

View file

@ -48,7 +48,7 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _WIN32
#if !defined(_WIN32) && !defined(CMAKE_BUILD)
#include "../acconf.h"
#endif

View file

@ -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

View file

@ -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;

View file

@ -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))

View file

@ -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:

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -45,6 +45,7 @@
#include <mmsystem.h>
#include <dsound.h>
#include <cguid.h>
namespace {
class DirectSoundPlayer;

View file

@ -48,6 +48,7 @@
#include <mmsystem.h>
#include <process.h>
#include <dsound.h>
#include <cguid.h>
namespace {
class DirectSoundPlayer2Thread;

View file

@ -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);

View file

@ -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++;

View file

@ -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();
}

View file

@ -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);

View file

@ -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)

View file

@ -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__

View file

@ -35,7 +35,7 @@
#ifdef WITH_AVISYNTH
#include "avisynth_wrap.h"
#include "avisynth.h"
#include <avisynth.h>
#include "options.h"
#include <mutex>

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

View file

@ -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

View file

@ -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)

View file

@ -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 {

View file

@ -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); \
}

View file

@ -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?

View file

@ -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>());

View file

@ -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>());
}

View file

@ -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
View 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(&lt))
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(&lt))
{
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);
}

View file

@ -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));
}

View file

@ -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);

View file

@ -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) {

View file

@ -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"));

View file

@ -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();
}
}

View file

@ -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});

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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
View 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>

View file

@ -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

View file

@ -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

View 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();

View file

@ -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

View file

@ -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;

View file

@ -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");

View 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));
}
}

View 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()
};

View file

@ -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)
};

View file

@ -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,

View file

@ -286,6 +286,9 @@
],
"video/frame/prev/large" : [
"Alt-Left"
],
"time/align" : [
"KP_TAB"
]
},
"Translation Assistant" : {

View file

@ -42,6 +42,7 @@
"subtitle/select/visible",
"time/snap/scene",
"time/frame/current",
"time/align",
"",
"tool/style/manager",
"subtitle/properties",

View file

@ -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,

View file

@ -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>

View file

@ -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");

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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__

View file

@ -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());

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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))

View file

@ -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>

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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