Changes of Revision 10

sview.changes Changed
x
 
1
@@ -1,4 +1,54 @@
2
 -------------------------------------------------------------------
3
+Tue Aug 24 12:45:46 UTC 2021 - Luigi Baldoni <aloisio@gmx.com>
4
+
5
+- Update to version 20.08
6
+  * Added support for Equiangular Cubemaps (EAC).
7
+  version 20.05:
8
+  * Added Spanish translation files.
9
+  * Image Viewer - added trilinear texture filtering option
10
+    generating mip-maps.
11
+  * Image Viewer - support 1x6 cubemap layout.
12
+  * Image Viewer - panorama is now automatically enabled for
13
+    JPEG files with GPano:ProjectionType tag.
14
+  * Image Viewer - panorama is now automatically enabled for
15
+    JPEG files with 360Stereo/360Mono tags (game screenshots).
16
+  * Image Viewer - support DDS-packed cubemaps.
17
+  * Movie Player - image-based subtitles size can be now
18
+    adjusted.
19
+  * Movie Player - workaround subtitles seeking issues for
20
+    attached SRT files.
21
+  * Movie Player - fixed ASS subtitles formatting issue on files
22
+    without closure tags.
23
+  * Movie Player - added handling of image-based subtitles
24
+    encoded as stereoscopic pair (side-by-side).
25
+  * Image Viewer - fixed poor quality on saving JPEG (yuv420p)
26
+    image into PNG (rgb).
27
+  * Image Viewer - fixed displaying WebP images with alpha
28
+    channel (yuva pixel formats).
29
+  * fontconfig library is now used to retrieve paths to system
30
+    fonts.
31
+  version 19.08:
32
+  * Introduced VR180 (hemisphere) and cylindrical panorama input
33
+    support.
34
+  * Image Viewer now redirects video file to Movie Player and
35
+    vice versa.
36
+  * Added single-finger swipe gesture for opening next/previous
37
+    file in playlist.
38
+  * FFmpeg 4.1 support.
39
+  * Fixed sporadic text formatting issues.
40
+  version 17.10:
41
+  * Image Viewer - added Slideshow delay parameter to Settings.
42
+  * Movie Player - added general information about the stream
43
+    (bitrate, codec, PAR, DAR) in File Info dialog.
44
+  * Movie Player - fixed seeking to the very beginning of the
45
+    file.
46
+  * Movie Player - fixed (workaround) displaying attached image
47
+    within some mp3 files.
48
+  * Fixed text rendering artifacts when using glyphs with
49
+    kerning defined.
50
+  * Fixed compilation on glibc 2.26+.
51
+
52
+-------------------------------------------------------------------
53
 Fri May  4 14:03:47 UTC 2018 - olaf@aepfle.de
54
 
55
 - Use ffmpeg3 versions of pkgconfig(libav*)
56
sview.spec Changed
70
 
1
@@ -1,6 +1,7 @@
2
 #
3
 # spec file for package sview
4
 #
5
+# Copyright (c) 2021 Packman Team <packman@links2linux.de>
6
 # Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
7
 #
8
 # All modifications and additions to the file contributed by third parties
9
@@ -16,27 +17,27 @@
10
 #
11
 
12
 
13
-%define src_ver 17_04
14
+%define src_ver 20_08
15
 %define src_name sView
16
 %define ffmpeg_includedir %(pkg-config --variable=includedir libavcodec)
17
 Name:           sview
18
-Version:        17.04
19
+Version:        20.08
20
 Release:        0
21
 Summary:        Stereoscopic media player
22
-License:        GPL-3.0+ and LGPL-3.0+
23
+License:        GPL-3.0-or-later AND LGPL-3.0-or-later
24
 Group:          Productivity/Multimedia/Video/Players
25
-Url:            http://www.sview.ru/en/
26
+URL:            http://www.sview.ru/en/
27
 Source:         https://github.com/gkv311/sview/archive/%{src_ver}.tar.gz#/%{name}-%{src_ver}.tar.gz
28
 BuildRequires:  dos2unix
29
-BuildRequires:  gcc-c++
30
 BuildRequires:  fdupes
31
+BuildRequires:  gcc-c++
32
 BuildRequires:  hicolor-icon-theme
33
 BuildRequires:  make
34
 BuildRequires:  pkgconfig
35
 BuildRequires:  update-desktop-files
36
+BuildRequires:  pkgconfig(freetype2)
37
 BuildRequires:  pkgconfig(gl)
38
 BuildRequires:  pkgconfig(gtk+-2.0)
39
-BuildRequires:  pkgconfig(freetype2)
40
 BuildRequires:  pkgconfig(libavcodec) = 57.107.100
41
 BuildRequires:  pkgconfig(libavformat) = 57.83.100
42
 BuildRequires:  pkgconfig(libavutil) = 55.78.100
43
@@ -48,7 +49,6 @@
44
 Requires:       xdg-utils
45
 #Recommends:     mongoose
46
 ExclusiveArch:  %{ix86} x86_64
47
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
48
 
49
 %description
50
 Stereoscopic Image Viewer and Movie Player.
51
@@ -66,7 +66,7 @@
52
     -e '/^CFLAGS/s/$/\ %{optflags}/' \
53
     -e '/^CXXFLAGS/s/$/\ %{optflags}/' \
54
     -i Makefile
55
-# Remove %%_smp_mflags to avoid compilation errors
56
+# Remove %%{?_smp_mflags} to avoid compilation errors
57
 make -j1 EXTRA_LDFLAGS="-Wl,-rpath,%{_libdir}/%{src_name}"
58
 
59
 %install
60
@@ -98,8 +98,7 @@
61
 %desktop_database_postun
62
 
63
 %files
64
-%defattr(-,root,root)
65
-%doc LICENSE*
66
+%license LICENSE*
67
 %{_bindir}/%{src_name}
68
 %{_libdir}/%{src_name}/
69
 %{_datadir}/applications/%{src_name}IV.desktop
70
sview-17_04.tar.gz/.gitignore -> sview-20_08.tar.gz/.gitignore Changed
16
 
1
@@ -1,5 +1,6 @@
2
 *.o
3
 *.obj
4
+*.class
5
 *.a
6
 *.vcxproj.user
7
 sView.Cpp.Custom.props
8
@@ -32,6 +33,7 @@
9
 Doxygen/
10
 distribution/repository/
11
 distribution/temp/
12
+distribution/build-*
13
 3rdparty/atlmfc
14
 3rdparty/OCCT/inc/
15
 3rdparty/OCCT/lib/
16
sview-17_04.tar.gz/.travis.yml -> sview-20_08.tar.gz/.travis.yml Changed
29
 
1
@@ -25,6 +25,9 @@
2
 sudo: required
3
 dist: trusty
4
 
5
+# require Ubuntu 16.04 Xenial Xerus
6
+#dist: xenial
7
+
8
 addons:
9
   apt:
10
     packages:
11
@@ -41,10 +44,14 @@
12
       - libavformat-dev
13
       - libavutil-dev
14
       - libswscale-dev
15
+  homebrew:
16
+    packages:
17
+      - freetype
18
+      - ffmpeg
19
+    update: true
20
 
21
-before_install:
22
-  - if [[ "$MY_TARGET" == "osx" ]]; then brew update; fi
23
-  - if [[ "$MY_TARGET" == "osx" ]]; then brew install freetype ffmpeg; fi
24
+#before_install:
25
+#  - if [[ "$MY_TARGET" == "osx" ]]; then brew update; fi
26
 
27
 install: true
28
 
29
sview-17_04.tar.gz/3rdparty/FFmpeg/rebuild.sh -> sview-20_08.tar.gz/3rdparty/FFmpeg/rebuild.sh Changed
231
 
1
@@ -4,12 +4,13 @@
2
 
3
 echo "Usage: $0 [FFmpegPath] [GPL || LGPL] [DEBUG || RELEASE] [GCC_PREFIX]"
4
 
5
-rebuildTarget="FFmpeg"
6
-rebuildLicense="LGPL"
7
+rebuildTarget="ffmpeg.git"
8
+rebuildLicense="lgpl"
9
 rebuildDebug="false"
10
 rebuildAndroid="false"
11
 compilerPrefix=""
12
 androidTarget=""
13
+androidAbi="armeabi-v7a"
14
 androidNdkRoot="$HOME/develop/android-ndk-r12b"
15
 aSystem=`uname -s`
16
 aPwdBack=$PWD
17
@@ -17,9 +18,9 @@
18
 for i in $*
19
 do
20
   if [ "$i" == "gpl"       ] || [ "$i" == "GPL" ]; then
21
-    rebuildLicense="GPL"
22
+    rebuildLicense="gpl"
23
   elif [ "$i" == "lgpl"    ] || [ "$i" == "LGPL" ]; then
24
-    rebuildLicense="LGPL"
25
+    rebuildLicense="lgpl"
26
   elif [ "$i" == "android" ]; then
27
     rebuildAndroid="true"
28
   elif [ "$i" == "debug"   ] || [ "$i" == "DEBUG" ]; then
29
@@ -51,8 +52,10 @@
30
 if [ "$rebuildAndroid" == "true" ]; then
31
   if [ "$androidTarget" == "arm64" ]; then
32
     aPrefixShort="aarch64-linux-android"
33
+    androidAbi="arm64-v8a"
34
   else
35
     aPrefixShort="arm-linux-androideabi"
36
+    androidAbi="armeabi-v7a"
37
   fi
38
 
39
   compilerPrefix="${androidNdkRoot}/toolchains/${aPrefixShort}-4.8/prebuilt/linux-x86_64/bin/${aPrefixShort}-"
40
@@ -72,18 +75,19 @@
41
 echo "  Start building FFmpeg $rebuildLicense from $rebuildTarget"
42
 cd $rebuildTarget
43
 
44
-# releases extract the version number from the VERSION file
45
-ffmpegVersion=$(cat VERSION 2> /dev/null)
46
+# releases extract the version number from the RELEASE file
47
+ffmpegVersion=$(cat RELEASE 2> /dev/null)
48
 ffmpegRevision=$(git log -1 --pretty=format:%h 2> /dev/null)
49
 ffmpegDate=$(git show -s --format="%ci" 2> /dev/null)
50
 ffmpegDate=${ffmpegDate:0:10}
51
-test $ffmpegRevision && ffmpegRevision=git-$ffmpegRevision
52
+test $ffmpegRevision && ffmpegRevision=git-$ffmpegDate-$ffmpegRevision
53
 test $ffmpegVersion || ffmpegVersion=$ffmpegRevision
54
 
55
 # remove slashes
56
 rebuildTarget="${rebuildTarget//\//}"
57
-SOURCES_NAME="FFmpeg-$ffmpegDate-$ffmpegVersion"
58
-OUTPUT_NAME="$SOURCES_NAME-$gccMachine-$gccVersion-$rebuildLicense"
59
+SOURCES_NAME="ffmpeg-$ffmpegVersion"
60
+#OUTPUT_NAME="$SOURCES_NAME-$gccMachine-$gccVersion-$rebuildLicense"
61
+OUTPUT_NAME="$SOURCES_NAME-$gccMachine-$rebuildLicense"
62
 SOURCES_NAME="$SOURCES_NAME-src"
63
 if [ "$rebuildDebug" == "true" ]; then
64
   OUTPUT_NAME="$OUTPUT_NAME-debug"
65
@@ -97,9 +101,9 @@
66
   OUTPUT_FOLDER_LIB="$OUTPUT_FOLDER/Frameworks"
67
 fi
68
 if [ "$androidTarget" == "arm64" ]; then
69
-  OUTPUT_FOLDER_LIB="$OUTPUT_FOLDER/libs/arm64-v8a"
70
+  OUTPUT_FOLDER_LIB="$OUTPUT_FOLDER/libs/$androidAbi"
71
 elif [ "$androidTarget" == "arm" ]; then
72
-  OUTPUT_FOLDER_LIB="$OUTPUT_FOLDER/libs/armeabi-v7a"
73
+  OUTPUT_FOLDER_LIB="$OUTPUT_FOLDER/libs/$androidAbi"
74
 fi
75
 
76
 rm -f -r $OUTPUT_FOLDER
77
@@ -115,6 +119,12 @@
78
 mkdir -p $OUTPUT_FOLDER_INC/libswscale
79
 mkdir -p $OUTPUT_FOLDER_INC/libswresample
80
 
81
+# include some information about FFmpeg into archive
82
+echo \<pre\>> $OUTPUT_FOLDER/VERSION.html
83
+git status >> $OUTPUT_FOLDER/VERSION.html
84
+git log -n 100 >> $OUTPUT_FOLDER/VERSION.html
85
+echo \</pre\>>> $OUTPUT_FOLDER/VERSION.html
86
+
87
 echo "  make distclean"
88
 make distclean &>/dev/null
89
 
90
@@ -125,10 +135,17 @@
91
   then
92
     echo "Sources archive '$SOURCES_NAME.7z' already exists"
93
   else
94
+
95
+    if [ ! -f ../exclude.lst ]; then
96
+      echo -e ".svn\n.git\n" > ../exclude.lst
97
+    fi
98
     7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on ../$SOURCES_NAME.7z ../$rebuildTarget '-xr@../exclude.lst'
99
   fi
100
 fi
101
 
102
+# --extra-cflags parameters
103
+anExtraCFlags=
104
+
105
 #--enable-memalign-hack
106
 configArguments="\
107
  --extra-version=sView.ru \
108
@@ -138,7 +155,6 @@
109
  --enable-avfilter \
110
  --enable-hardcoded-tables \
111
  --enable-pthreads \
112
- --disable-libopenjpeg \
113
  --disable-doc \
114
  --enable-runtime-cpudetect"
115
 
116
@@ -147,6 +163,8 @@
117
   configArguments="$configArguments --enable-vda --libdir=@executable_path/../Frameworks"
118
 fi
119
 
120
+export PKG_CONFIG_LIBDIR=
121
+
122
 #if [ "$gccMachine" != "$GCC_MACHINE_LINUX_64" ]; then
123
 if [ "$gccMachine" == "$GCC_MACHINE_MINGW_32" ] || [ "$gccMachine" == "$GCC_MACHINE_MINGW_32_1" ] \
124
 || [ "$gccMachine" == "$GCC_MACHINE_MINGW_64" ] || [ "$gccMachine" == "$GCC_MACHINE_MINGW_64_1" ]; then
125
@@ -154,14 +172,19 @@
126
   # you should use with --enable-pthreads instead to enable full multithreading support!
127
   #configArguments="$configArguments --enable-w32threads"
128
   configArguments="$configArguments --disable-w32threads"
129
-  if [ "$rebuildLicense" == "GPL" ]; then
130
+  if [ "$rebuildLicense" == "gpl" ]; then
131
     configArguments="$configArguments --enable-avisynth"
132
   fi
133
 
134
+  aMingwRoot=${compilerPrefix::-1}
135
+  export PKG_CONFIG_LIBDIR=/usr/$aMingwRoot/share/pkgconfig
136
+
137
   configArguments="$configArguments --enable-libopenjpeg"
138
 
139
   # avoid dynamic linkage with libgcc_s_sjlj-1.dll
140
   configArguments="$configArguments --extra-ldflags=-static-libgcc"
141
+else
142
+  configArguments="$configArguments --disable-libopenjpeg"
143
 fi
144
 
145
 # cross-compiling options
146
@@ -169,19 +192,31 @@
147
   targetFlags="--cross-prefix=$compilerPrefix --arch=x86_32"
148
   configArguments="$configArguments --enable-cross-compile --target-os=mingw32 $targetFlags"
149
 elif [ "$gccMachine" == "$GCC_MACHINE_MINGW_64" ] || [ "$gccMachine" == "$GCC_MACHINE_MINGW_64_1" ]; then
150
+  anExtraCFlags="$anExtraCFlags -Dstrtod=__strtod"
151
   targetFlags="--cross-prefix=$compilerPrefix --arch=x86_64 --extra-cflags=-Dstrtod=__strtod"
152
   configArguments="$configArguments --enable-cross-compile --target-os=mingw32 $targetFlags"
153
 elif [ "$rebuildAndroid" == "true" ]; then
154
+  anAndArch=arm
155
+  anAndSysRoot=${androidNdkRoot}/platforms/android-15/arch-arm
156
   if [ "$androidTarget" == "arm64" ]; then
157
-    targetFlags="--cross-prefix=$compilerPrefix --sysroot=${androidNdkRoot}/platforms/android-21/arch-arm64 --arch=aarch64"
158
-  else
159
-    targetFlags="--cross-prefix=$compilerPrefix --sysroot=${androidNdkRoot}/platforms/android-15/arch-arm --arch=arm"
160
+    anAndArch=aarch64
161
+    anAndSysRoot=${androidNdkRoot}/platforms/android-21/arch-arm64
162
   fi
163
+  configArguments="$configArguments --enable-cross-compile --target-os=android --cross-prefix=$compilerPrefix --sysroot=${anAndSysRoot} --arch=${anAndArch}"
164
+  #if [ -x "${androidNdkRoot}/sysroot" ]; then
165
+    #configArguments="$configArguments --sysinclude=${androidNdkRoot}/sysroot/usr/include"
166
+  #fi
167
 
168
-  configArguments="$configArguments --enable-cross-compile --target-os=android $targetFlags"
169
-  #configArguments="$configArguments --extra-cflags='-fno-builtin-sin -fno-builtin-sinf'"
170
+  if [ "$androidTarget" == "arm64" ]; then
171
+    anExtraCFlags="$anExtraCFlags -march=armv8-a"
172
+  else
173
+    anExtraCFlags="$anExtraCFlags -march=armv7-a -mfloat-abi=softfp -fno-builtin-sin -fno-builtin-sinf"
174
+  fi
175
 
176
   configArguments="$configArguments --enable-jni --enable-mediacodec"
177
+
178
+  configArguments="$configArguments --enable-mbedtls --extra-ldflags=-L$aPwdBack/mbedtls-2.16.2-android/libs/$androidAbi"
179
+  anExtraCFlags="$anExtraCFlags -I$aPwdBack/mbedtls-2.16.2-android/include"
180
 fi
181
 
182
 # More options
183
@@ -200,7 +235,7 @@
184
 # enable (L)GPL version 3
185
 configArguments="$configArguments --enable-version3"
186
 
187
-if [ "$rebuildLicense" == "GPL" ]; then
188
+if [ "$rebuildLicense" == "gpl" ]; then
189
   configArguments="$configArguments --enable-gpl"
190
   # enable libx264 encoder (should be compiled and installed!)
191
   #configArguments="$configArguments --enable-libx264"
192
@@ -212,30 +247,28 @@
193
 set -o pipefail
194
 
195
 aNbJobs="$(getconf _NPROCESSORS_ONLN)"
196
+"$compilerPrefix"gcc --version > $OUTPUT_FOLDER/gccInfo-$gccMachine-$rebuildLicense.log
197
+
198
+# --extra-cflags should be passed as single dedicated argument
199
+anExtraCFlags="--extra-cflags=${anExtraCFlags}"
200
 
201
 echo
202
-echo "  ./configure $configArguments"
203
+echo "  ./configure $configArguments $anExtraCFlags"
204
 echo
205
 if [ "$rebuildAndroid" == "true" ]; then
206
-  if [ "$androidTarget" == "arm64" ]; then
207
-    ./configure $configArguments --disable-symver --extra-cflags='-march=armv8-a' 2>&1 | tee $OUTPUT_FOLDER/config.log
208
-  else
209
-    ./configure $configArguments --disable-symver --extra-cflags='-march=armv7-a -mfloat-abi=softfp -fno-builtin-sin -fno-builtin-sinf' 2>&1 | tee $OUTPUT_FOLDER/config.log
210
-  fi
211
+  ./configure $configArguments --disable-symver "$anExtraCFlags" 2>&1 | tee $OUTPUT_FOLDER/config-$gccMachine-$rebuildLicense.log
212
 else
213
-  ./configure $configArguments 2>&1 | tee -a $OUTPUT_FOLDER/config.log
214
+  ./configure $configArguments 2>&1 | tee -a $OUTPUT_FOLDER/config-$gccMachine-$rebuildLicense.log
215
 fi
216
 aResult=$?; if [[ $aResult != 0 ]]; then exit $aResult; fi
217
 
218
-make -j $aNbJobs 2>&1 | tee -a $OUTPUT_FOLDER/make.log
219
+make -j $aNbJobs 2>&1 | tee -a $OUTPUT_FOLDER/make-$gccMachine-$rebuildLicense.log
220
 aResult=$?; if [[ $aResult != 0 ]]; then exit $aResult; fi
221
 
222
 # Now copy result files
223
 echo
224
 echo "  Now copy result files into $OUTPUT_FOLDER"
225
 
226
-"$compilerPrefix"gcc --version > $OUTPUT_FOLDER/gccInfo.log
227
-
228
 if [ -f libavcodec/avcodec.dll ]; then
229
   cp -f libavcodec/*.dll $OUTPUT_FOLDER_BIN
230
   cp -f libavcodec/*.lib $OUTPUT_FOLDER_LIB &>/dev/null
231
sview-17_04.tar.gz/3rdparty/include/mongoose.c -> sview-20_08.tar.gz/3rdparty/include/mongoose.c Changed
12
 
1
@@ -23,6 +23,10 @@
2
   #ifndef _CRT_SECURE_NO_WARNINGS
3
     #define _CRT_SECURE_NO_WARNINGS
4
   #endif
5
+  #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
6
+    // Warning C4996 'inet_ntoa': Use inet_ntop() or InetNtop() instead
7
+    #define _WINSOCK_DEPRECATED_NO_WARNINGS
8
+  #endif
9
 #else
10
 #ifdef __linux__
11
 #define _XOPEN_SOURCE 600     // For flockfile() on Linux
12
sview-20_08.tar.gz/3rdparty/mbedtls Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/3rdparty/mbedtls/sview_mbedtls_build_android.bat Added
94
 
1
@@ -0,0 +1,92 @@
2
+@echo OFF
3
+
4
+rem Auxiliary script for semi-automated building of mbedtls (https://tls.mbed.org/) for Android platform.
5
+rem Script should be placed into root of mbedtls repository, edited with paths
6
+rem to CMake, 3rd-parties, Android NDK and MinGW64 make tool.
7
+
8
+rem CMake toolchain definition should be cloned from the following git repository:
9
+rem https://github.com/taka-no-me/android-cmake
10
+
11
+rem CMake can be downloaded from official site:
12
+rem https://cmake.org/download/
13
+
14
+rem Android NDK can be downloaded from offical site:
15
+rem https://developer.android.com/ndk/downloads
16
+
17
+rem x86 build is broken on old gcc due to https://github.com/ARMmbed/mbedtls/issues/1910
18
+rem include/mbedtls/bn_mul.h
19
+rem -#if defined(__i386__) && defined(__OPTIMIZE__) && !defined(__ANDROID__)
20
+rem +#if defined(__i386__) && defined(__OPTIMIZE__) && !defined(__ANDROID__)
21
+rem
22
+rem #define MULADDC_INIT
23
+
24
+set "anMbedTlsSrc=%~dp0"
25
+set aNbJobs=%NUMBER_OF_PROCESSORS%
26
+
27
+call c:\develop\MinGW\TDM-GCC-64\mingwvars.bat
28
+set "PATH=c:\develop\CMake\bin;%PATH%"
29
+set "anNdkPath=c:/develop/android/android-ndk-r12"
30
+set "aToolchain=c:/develop/android-cmake/android.toolchain.cmake"
31
+
32
+set "anInstDir=%~dp0work/mbedtls-android"
33
+if exist "%anInstDir%" ( rmdir /S /Q "%anInstDir%" )
34
+
35
+call :cmakeGenerate "15" "armeabi-v7a"
36
+call :cmakeGenerate "21" "arm64-v8a"
37
+call :cmakeGenerate "15" "x86"
38
+
39
+pause
40
+
41
+goto :eof
42
+
43
+:cmakeGenerate
44
+set "anApi=%1"
45
+set "anAbi=%2"
46
+set "aPlatformAndCompiler=android-%anAbi%-gcc"
47
+set "aWorkDir=work\%aPlatformAndCompiler%-make"
48
+set "aLogFile=%~dp0build-%anAbi%.log"
49
+if not exist "%aWorkDir%" ( mkdir "%aWorkDir%" )
50
+if     exist "%aLogFile%" ( del   "%aLogFile%" )
51
+
52
+pushd "%aWorkDir%"
53
+
54
+echo Configuring mbedtls for Android %anAbi% (API level %anApi%)...
55
+cmake -G "MinGW Makefiles" ^
56
+ -D CMAKE_TOOLCHAIN_FILE:FILEPATH="%aToolchain%" ^
57
+ -D ANDROID_NDK:FILEPATH="%anNdkPath%" ^
58
+ -D CMAKE_BUILD_TYPE:STRING="Release" ^
59
+ -D ANDROID_ABI:STRING="%anAbi%" ^
60
+ -D ANDROID_NATIVE_API_LEVEL:STRING="%anApi%" ^
61
+ -D ANDROID_STL:STRING="gnustl_shared" ^
62
+ -D CMAKE_INSTALL_PREFIX:PATH="%anInstDir%" ^
63
+ -D LIBRARY_OUTPUT_PATH:PATH="%anInstDir%/libs/%anAbi%" ^
64
+ -D USE_SHARED_MBEDTLS_LIBRARY:BOOL="OFF" ^
65
+ -D USE_STATIC_MBEDTLS_LIBRARY:BOOL="ON" ^
66
+ -D ENABLE_TESTING:BOOL="OFF" ^
67
+ -D ENABLE_PROGRAMS:BOOL="OFF" ^
68
+ "%anMbedTlsSrc%"
69
+
70
+if errorlevel 1 (
71
+  popd
72
+  pause
73
+  exit /B
74
+  goto :eof
75
+)
76
+
77
+mingw32-make clean
78
+
79
+echo Building mbedtls...
80
+mingw32-make -j %aNbJobs% 2>> %aLogFile%
81
+type %aLogFile%
82
+if errorlevel 1 (
83
+  popd
84
+  pause
85
+  exit /B
86
+  goto :eof
87
+)
88
+echo Installing mbedtls into %~dp0work/%aPlatformAndCompiler%...
89
+mingw32-make install 2>> %aLogFile%
90
+if exist "%anInstDir%/lib" ( rmdir /S /Q "%anInstDir%/lib" )
91
+
92
+popd
93
+goto :eof
94
sview-17_04.tar.gz/Makefile -> sview-20_08.tar.gz/Makefile Changed
518
 
1
@@ -2,6 +2,8 @@
2
 
3
 WORKDIR = $(shell pwd)
4
 SRCDIR = $(WORKDIR)
5
+JAVA_HOME = /usr
6
+APP_PREFIX = /usr
7
 
8
 $(info SRCDIR=$(SRCDIR))
9
 
10
@@ -13,7 +15,17 @@
11
 .mm.o:
12
    $(CXX) -c $(CXXFLAGS) $< -o $@
13
 
14
+# Compile java files.
15
+# javac takes output folder, not file, and actually sometimes generates multiple files from single .java input.
16
+# To fool make (avoid recompiling on each build) - copy result .class file to source folder;
17
+# this, however, might lead to incomplete build on .java change without make clean.
18
+.SUFFIXES: .class .java
19
+.java.class:
20
+   $(JAVA_HOME)/bin/javac -source 1.7 -target 1.7 -d $(BUILD_ROOT)/java/classes -classpath $(ANDROID_PLATFORM) -sourcepath $(SRCDIR)/sview/src:$(BUILD_ROOT)/java/gen $<
21
+   cp -f $(BUILD_ROOT)/java/classes/com/sview/$(@F) $@
22
+
23
 TARGET_OS = linux
24
+TARGET_ARCH2 =
25
 
26
 #ANDROID_NDK = $(HOME)/develop/android-ndk-r12b
27
 ifeq ($(OS),Windows_NT)
28
@@ -25,6 +37,7 @@
29
 endif
30
 ifeq ($(UNAME_S),Darwin)
31
 TARGET_OS = osx
32
+TARGET_OS_VERSION = 10.10
33
 endif
34
 endif
35
 
36
@@ -40,12 +53,19 @@
37
 BUILD_ROOT = $(BUILD_ROOT_BUNDLE)/Contents/MacOS
38
 endif
39
 
40
+ST_DEBUG = 0
41
 FFMPEG_ROOT =
42
 FREETYPE_ROOT =
43
 OPENAL_ROOT =
44
 LIBCONFIG_ROOT =
45
 LIBSUBFOLDER = lib
46
 LIBSUFFIX = so
47
+ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.3
48
+ANDROID_PLATFORM = $(ANDROID_HOME)/platforms/android-26/android.jar
49
+ANDROID_KEYSTORE = $(BUILD_ROOT)/sview_debug.key
50
+ANDROID_KEYSTORE_PASSWORD = sview_store_pswd
51
+ANDROID_KEY = "sview android key"
52
+ANDROID_KEY_PASSWORD = sview_pswd
53
 
54
 # function defining library install_name to @executable_path on OS X
55
 libinstname =
56
@@ -62,6 +82,7 @@
57
 LIB_CONFIG =
58
 LIB_ANDROID =
59
 LIB_IOKIT =
60
+LIB_COREVIDEO =
61
 LIB_OPENAL = -lopenal
62
 LIB_OUTPUTS = -lStOutAnaglyph -lStOutDual -lStOutInterlace -lStOutPageFlip -lStOutIZ3D -lStOutDistorted
63
 TOOLCHAIN =
64
@@ -81,7 +102,10 @@
65
 LIB_PTHREAD = -lobjc
66
 LIB_GLX = -framework OpenGL -framework Appkit
67
 LIB_IOKIT = -framework IOKit
68
-LIB_OPENAL = -framework OpenAL
69
+LIB_COREVIDEO = -framework CoreVideo
70
+ifeq ($(OPENAL_ROOT),)
71
+  LIB_OPENAL = -framework OpenAL
72
+endif
73
 endif
74
 
75
 # Android libraries
76
@@ -122,28 +146,45 @@
77
 LDSTRIP = -s
78
 LDZDEF = -z defs
79
 EXTRA_CFLAGS   =
80
-EXTRA_CXXFLAGS =
81
+EXTRA_CXXFLAGS = -DAPP_PREFIX="\"$(APP_PREFIX)\""
82
 EXTRA_LDFLAGS  =
83
 ifeq ($(TARGET_OS),osx)
84
 LDZDEF =
85
 endif
86
 
87
+CCVERSION := $(shell $(CC) -dumpversion)
88
+CCMACHINE := $(shell $(CC) -dumpmachine)
89
+
90
+ifneq (,$(findstring i586,$(CCMACHINE)))
91
+TARGET_ARCH2 = x86
92
+else ifneq (,$(findstring i686,$(CCMACHINE)))
93
+TARGET_ARCH2 = x86
94
+else ifneq (,$(findstring x86,$(CCMACHINE)))
95
+TARGET_ARCH2 = x86
96
+else ifneq (,$(findstring mingw,$(CCMACHINE)))
97
+TARGET_ARCH2 = x86
98
+endif
99
+
100
 # to activate debug build
101
+ifneq ($(ST_DEBUG),0)
102
+EXTRA_CXXFLAGS = -DST_DEBUG
103
+LDSTRIP =
104
+STRIPFLAGS = --info
105
+endif
106
 #EXTRA_CXXFLAGS = -DST_DEBUG_LOG_TO_FILE=\"/sdcard/Android/data/com.sview/files/sview.log\" -DST_DEBUG
107
 #EXTRA_CXXFLAGS += -DST_DEBUG_GL
108
 #EXTRA_CXXFLAGS += -DST_DEBUG_FFMPEG_VERBOSE
109
 #EXTRA_CXXFLAGS += -DST_DEBUG_SYSLOG
110
 #EXTRA_CXXFLAGS += -DST_DEBUG_THREADID
111
-#LDSTRIP =
112
-#STRIPFLAGS = --info
113
 
114
 ifdef ANDROID_NDK
115
 LIBSUBFOLDER = libs/$(ANDROID_EABI)
116
 EXTRA_CFLAGS   += $(ANDROID_SYSROOT) $(ANDROID_MARCH)
117
 EXTRA_CXXFLAGS += $(ANDROID_SYSROOT) $(ANDROID_MARCH)
118
-EXTRA_CXXFLAGS += -I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/include -I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(ANDROID_EABI)/include -DST_HAVE_EGL -DST_NO_UPDATES_CHECK
119
+EXTRA_CXXFLAGS += -I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/include -I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(ANDROID_EABI)/include -DST_HAVE_EGL
120
 EXTRA_LDFLAGS  += $(ANDROID_SYSROOT) -L$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(ANDROID_EABI) -lstdc++ -lgnustl_shared
121
-else
122
+else ifeq ($(TARGET_ARCH2),x86)
123
+# necessary for 32-bit x86 builds, where MMX and SSE are not enabled by default
124
 EXTRA_CFLAGS   += -mmmx -msse
125
 EXTRA_CXXFLAGS += -mmmx -msse
126
 endif
127
@@ -152,6 +193,13 @@
128
 # todo
129
 LDSTRIP =
130
 
131
+# minimal supported version of macOS:
132
+# - CMake: CMAKE_OSX_DEPLOYMENT
133
+# - qmake: QMAKE_MACOSX_DEPLOYMENT_TARGET = $(TARGET_OS_VERSION)
134
+# - environment variable: export MACOSX_DEPLOYMENT_TARGET=$(TARGET_OS_VERSION)
135
+EXTRA_CFLAGS   += -mmacosx-version-min=$(TARGET_OS_VERSION)
136
+EXTRA_CXXFLAGS += -mmacosx-version-min=$(TARGET_OS_VERSION)
137
+
138
 # workaround homebrew
139
 HAS_PKGCONF := $(shell command -v pkg-config 2> /dev/null)
140
 ifdef HAS_PKGCONF
141
@@ -182,11 +230,23 @@
142
 
143
 ifeq ($(TARGET_OS),linux)
144
 EXTRA_CXXFLAGS += `pkg-config gtk+-2.0 --cflags`
145
+# notification about updates available on sview.ru
146
+#EXTRA_CXXFLAGS += -DST_UPDATES_CHECK
147
+endif
148
+
149
+# optionally fail on any compiler warning except #warning and deprecations
150
+WERROR_LEVEL = 0
151
+ifeq ($(WERROR_LEVEL),1)
152
+EXTRA_CXXFLAGS += -Werror -Wno-error=cpp -Wno-error=deprecated-declarations
153
 endif
154
 
155
 INC =  -I$(SRCDIR)/3rdparty/include -I$(SRCDIR)/include
156
 CFLAGS   = -fPIC $(HAVE_MONGOOSE) $(INC) $(EXTRA_CFLAGS)
157
+ifneq ($(ST_DEBUG),0)
158
+CXXFLAGS = -g -std=c++0x -Wall -fPIC $(HAVE_MONGOOSE) $(INC) $(EXTRA_CXXFLAGS)
159
+else
160
 CXXFLAGS = -O3 -std=c++0x -Wall -fPIC $(HAVE_MONGOOSE) $(INC) $(EXTRA_CXXFLAGS)
161
+endif
162
 LIBDIR = -L$(BUILD_ROOT)
163
 LIB =
164
 LDFLAGS = $(LDSTRIP) $(LDZDEF) $(EXTRA_LDFLAGS)
165
@@ -207,13 +267,16 @@
166
 sViewAndroidCad := libsviewcad.$(LIBSUFFIX)
167
 sView           := sView
168
 sViewAndroid    := libsview.$(LIBSUFFIX)
169
-
170
-aDestAndroid    := sview
171
-
172
-all:         pre_all $(aStShared) $(aStGLWidgets) $(aStCore) $(aStOutAnaglyph) $(aStOutDual) $(aStOutInterlace) $(aStOutPageFlip) $(aStOutIZ3D) $(aStOutDistorted) $(aStImageViewer) $(aStMoviePlayer) $(aStDiagnostics) $(sView)
173
-android_cad: aDestAndroid = StCADViewer
174
-android_cad: pre_all $(aStShared) $(aStGLWidgets) $(aStCore) $(aStOutAnaglyph) $(aStOutInterlace) $(aStOutDistorted) $(aStImageViewer) $(aStMoviePlayer) $(sViewAndroidCad) install_android install_android_cad_libs
175
-android:     pre_all $(aStShared) $(aStGLWidgets) $(aStCore) $(aStOutAnaglyph) $(aStOutInterlace) $(aStOutDistorted) $(aStImageViewer) $(aStMoviePlayer) $(sViewAndroid)    install_android install_android_libs
176
+sViewApk        := $(SRCDIR)/build/sView.apk
177
+sViewApkSigned  := $(SRCDIR)/build/sView.signed.apk.tmp
178
+sViewApkUnsigned:= $(SRCDIR)/build/sView.unsigned.apk.tmp
179
+aDestAndroid    := build/apk-tmp
180
+sViewDex        := $(aDestAndroid)/classes.dex
181
+
182
+all:         shared $(aStDiagnostics) $(sView)
183
+android_cad: pre_all_android shared $(sViewAndroidCad) $(sViewApk) install_android install_android_cad_libs
184
+android:     pre_all_android shared $(sViewAndroid)    $(sViewApk) install_android install_android_libs
185
+shared:      pre_all $(aStShared) $(aStGLWidgets) $(aStCore) outputs_all $(aStImageViewer) $(aStMoviePlayer)
186
 clean:       clean_StShared clean_StGLWidgets clean_StCore clean_sView clean_StOutAnaglyph clean_StOutDual clean_StOutInterlace clean_StOutPageFlip clean_StOutIZ3D clean_StOutDistorted clean_StImageViewer clean_StMoviePlayer clean_StDiagnostics clean_StCADViewer clean_sViewAndroid
187
 distclean:   clean
188
 
189
@@ -224,33 +287,34 @@
190
 endif
191
 
192
 install:
193
-   mkdir -p $(DESTDIR)/usr/bin
194
-   mkdir -p $(DESTDIR)/usr/$(USR_LIB)/sView
195
-   mkdir -p $(DESTDIR)/usr/$(USR_LIB)/firefox/plugins
196
-   mkdir -p $(DESTDIR)/usr/$(USR_LIB)/mozilla/plugins
197
-   mkdir -p $(DESTDIR)/usr/share
198
-   mkdir -p $(DESTDIR)/usr/share/sView/info
199
-   mkdir -p $(DESTDIR)/usr/share/sView/lang
200
-   mkdir -p $(DESTDIR)/usr/share/sView/shaders
201
-   mkdir -p $(DESTDIR)/usr/share/sView/textures
202
-   mkdir -p $(DESTDIR)/usr/share/sView/web
203
-   cp -f -r share/*                     $(DESTDIR)/usr/share/
204
-   cp -f -r $(BUILD_ROOT)/lang/*        $(DESTDIR)/usr/share/sView/lang/
205
-   cp -f -r $(BUILD_ROOT)/shaders/*     $(DESTDIR)/usr/share/sView/shaders/
206
-   cp -f -r $(BUILD_ROOT)/textures/*    $(DESTDIR)/usr/share/sView/textures/
207
-   cp -f -r $(BUILD_ROOT)/web/*         $(DESTDIR)/usr/share/sView/web/
208
-   cp -f    license-gpl-3.0.txt         $(DESTDIR)/usr/share/sView/info/license.txt
209
-   cp -f -r $(BUILD_ROOT)/*.$(LIBSUFFIX) $(DESTDIR)/usr/$(USR_LIB)/
210
-   cp -f    $(BUILD_ROOT)/sView         $(DESTDIR)/usr/$(USR_LIB)/sView/sView
211
-   ln --force --symbolic ../$(USR_LIB)/sView/sView       $(DESTDIR)/usr/bin/sView
212
-   ln --force --symbolic ../../share/sView/demo/demo.jps $(DESTDIR)/usr/$(USR_LIB)/sView/demo.jps
213
-   rm -f    $(DESTDIR)/usr/$(USR_LIB)/sView/*.a
214
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/bin
215
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/sView
216
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/firefox/plugins
217
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/mozilla/plugins
218
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share
219
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share/sView/info
220
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share/sView/lang
221
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share/sView/shaders
222
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share/sView/textures
223
+   mkdir -p $(DESTDIR)/$(APP_PREFIX)/share/sView/web
224
+   cp -f -r share/*                     $(DESTDIR)/$(APP_PREFIX)/share/
225
+   cp -f -r $(BUILD_ROOT)/lang/*        $(DESTDIR)/$(APP_PREFIX)/share/sView/lang/
226
+   cp -f -r $(BUILD_ROOT)/shaders/*     $(DESTDIR)/$(APP_PREFIX)/share/sView/shaders/
227
+   cp -f -r $(BUILD_ROOT)/textures/*    $(DESTDIR)/$(APP_PREFIX)/share/sView/textures/
228
+   cp -f -r $(BUILD_ROOT)/web/*         $(DESTDIR)/$(APP_PREFIX)/share/sView/web/
229
+   cp -f    license-gpl-3.0.txt         $(DESTDIR)/$(APP_PREFIX)/share/sView/info/license.txt
230
+   cp -f -r $(BUILD_ROOT)/*.$(LIBSUFFIX) $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/
231
+   cp -f    $(BUILD_ROOT)/sView         $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/sView/sView
232
+   ln --force --symbolic ../$(USR_LIB)/sView/sView       $(DESTDIR)/$(APP_PREFIX)/bin/sView
233
+   ln --force --symbolic ../../share/sView/demo/demo.jps $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/sView/demo.jps
234
+   rm -f    $(DESTDIR)/$(APP_PREFIX)/$(USR_LIB)/sView/*.a
235
 
236
 install_android:
237
    mkdir -p $(aDestAndroid)/assets/info
238
    mkdir -p $(aDestAndroid)/assets/lang/German
239
    mkdir -p $(aDestAndroid)/assets/lang/French
240
    mkdir -p $(aDestAndroid)/assets/lang/English
241
+   mkdir -p $(aDestAndroid)/assets/lang/Spanish
242
    mkdir -p $(aDestAndroid)/assets/lang/Russian
243
    mkdir -p $(aDestAndroid)/assets/lang/Czech
244
    mkdir -p $(aDestAndroid)/assets/lang/ChineseS
245
@@ -260,6 +324,7 @@
246
    cp -f -r $(BUILD_ROOT)/lang/Deutsch/*  $(aDestAndroid)/assets/lang/German/
247
    cp -f -r $(BUILD_ROOT)/lang/français/* $(aDestAndroid)/assets/lang/French/
248
    cp -f -r $(BUILD_ROOT)/lang/English/*  $(aDestAndroid)/assets/lang/English/
249
+   cp -f -r $(BUILD_ROOT)/lang/Español/*  $(aDestAndroid)/assets/lang/Spanish/
250
    cp -f -r $(BUILD_ROOT)/lang/русский/*  $(aDestAndroid)/assets/lang/Russian/
251
    cp -f -r $(BUILD_ROOT)/lang/Czech/*    $(aDestAndroid)/assets/lang/Czech/
252
    cp -f -r $(BUILD_ROOT)/lang/ChineseS/* $(aDestAndroid)/assets/lang/ChineseS/
253
@@ -267,51 +332,53 @@
254
    cp -f -r $(BUILD_ROOT)/shaders/*       $(aDestAndroid)/assets/shaders/
255
    cp -f -r $(BUILD_ROOT)/textures/*      $(aDestAndroid)/assets/textures/
256
    cp -f    license-gpl-3.0.txt           $(aDestAndroid)/assets/info/license.txt
257
+   $(ANDROID_BUILD_TOOLS)/aapt package -v -f -m -S $(SRCDIR)/sview/res -J $(BUILD_ROOT)/java/gen -M $(SRCDIR)/sview/AndroidManifest.xml -I $(ANDROID_PLATFORM)
258
 
259
 install_android_libs: $(aStShared) $(aStGLWidgets) $(aStCore) $(aStOutAnaglyph) $(aStOutInterlace) $(aStOutDistorted) $(aStImageViewer) $(aStMoviePlayer) $(sViewAndroid)
260
-   cp -f $(BUILD_ROOT)/$(aStShared)       $(aDestAndroid)/libs/$(ANDROID_EABI)/
261
-   cp -f $(BUILD_ROOT)/$(aStGLWidgets)    $(aDestAndroid)/libs/$(ANDROID_EABI)/
262
-   cp -f $(BUILD_ROOT)/$(aStCore)         $(aDestAndroid)/libs/$(ANDROID_EABI)/
263
-   cp -f $(BUILD_ROOT)/$(aStOutAnaglyph)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
264
-   cp -f $(BUILD_ROOT)/$(aStOutInterlace) $(aDestAndroid)/libs/$(ANDROID_EABI)/
265
-   cp -f $(BUILD_ROOT)/$(aStOutDistorted) $(aDestAndroid)/libs/$(ANDROID_EABI)/
266
-   cp -f $(BUILD_ROOT)/$(aStImageViewer)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
267
-   cp -f $(BUILD_ROOT)/$(aStMoviePlayer)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
268
-   cp -f $(BUILD_ROOT)/$(sViewAndroid)    $(aDestAndroid)/libs/$(ANDROID_EABI)/
269
-   cp -f $(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(ANDROID_EABI)/libgnustl_shared.so $(aDestAndroid)/libs/$(ANDROID_EABI)/
270
-   $(STRIP) $(STRIPFLAGS) $(aDestAndroid)/libs/$(ANDROID_EABI)/libgnustl_shared.so
271
-   cp -f $(FREETYPE_ROOT)/libs/$(ANDROID_EABI)/libfreetype.so    $(aDestAndroid)/libs/$(ANDROID_EABI)/
272
-   cp -f $(OPENAL_ROOT)/libs/$(ANDROID_EABI)/libopenal.so        $(aDestAndroid)/libs/$(ANDROID_EABI)/
273
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavcodec.so       $(aDestAndroid)/libs/$(ANDROID_EABI)/
274
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavdevice.so      $(aDestAndroid)/libs/$(ANDROID_EABI)/
275
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavformat.so      $(aDestAndroid)/libs/$(ANDROID_EABI)/
276
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavutil.so        $(aDestAndroid)/libs/$(ANDROID_EABI)/
277
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswresample.so    $(aDestAndroid)/libs/$(ANDROID_EABI)/
278
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswscale.so       $(aDestAndroid)/libs/$(ANDROID_EABI)/
279
+   cp -f $(BUILD_ROOT)/$(aStShared)       $(aDestAndroid)/lib/$(ANDROID_EABI)/
280
+   cp -f $(BUILD_ROOT)/$(aStGLWidgets)    $(aDestAndroid)/lib/$(ANDROID_EABI)/
281
+   cp -f $(BUILD_ROOT)/$(aStCore)         $(aDestAndroid)/lib/$(ANDROID_EABI)/
282
+   cp -f $(BUILD_ROOT)/$(aStOutAnaglyph)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
283
+   cp -f $(BUILD_ROOT)/$(aStOutInterlace) $(aDestAndroid)/lib/$(ANDROID_EABI)/
284
+   cp -f $(BUILD_ROOT)/$(aStOutDistorted) $(aDestAndroid)/lib/$(ANDROID_EABI)/
285
+   cp -f $(BUILD_ROOT)/$(aStImageViewer)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
286
+   cp -f $(BUILD_ROOT)/$(aStMoviePlayer)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
287
+   cp -f $(BUILD_ROOT)/$(sViewAndroid)    $(aDestAndroid)/lib/$(ANDROID_EABI)/
288
+   cp -f $(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(ANDROID_EABI)/libgnustl_shared.so $(aDestAndroid)/lib/$(ANDROID_EABI)/
289
+   $(STRIP) $(STRIPFLAGS) $(aDestAndroid)/lib/$(ANDROID_EABI)/libgnustl_shared.so
290
+   cp -f $(FREETYPE_ROOT)/libs/$(ANDROID_EABI)/libfreetype.so    $(aDestAndroid)/lib/$(ANDROID_EABI)/
291
+   cp -f $(OPENAL_ROOT)/libs/$(ANDROID_EABI)/libopenal.so        $(aDestAndroid)/lib/$(ANDROID_EABI)/
292
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavcodec.so       $(aDestAndroid)/lib/$(ANDROID_EABI)/
293
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavdevice.so      $(aDestAndroid)/lib/$(ANDROID_EABI)/
294
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavformat.so      $(aDestAndroid)/lib/$(ANDROID_EABI)/
295
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavutil.so        $(aDestAndroid)/lib/$(ANDROID_EABI)/
296
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswresample.so    $(aDestAndroid)/lib/$(ANDROID_EABI)/
297
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswscale.so       $(aDestAndroid)/lib/$(ANDROID_EABI)/
298
 
299
 install_android_cad_libs: $(aStShared) $(aStGLWidgets) $(aStCore) $(aStOutAnaglyph) $(aStOutInterlace) $(aStOutDistorted) $(aStImageViewer) $(aStMoviePlayer) $(sViewAndroidCad)
300
-   cp -f $(BUILD_ROOT)/$(aStShared)       $(aDestAndroid)/libs/$(ANDROID_EABI)/
301
-   cp -f $(BUILD_ROOT)/$(aStGLWidgets)    $(aDestAndroid)/libs/$(ANDROID_EABI)/
302
-   cp -f $(BUILD_ROOT)/$(aStCore)         $(aDestAndroid)/libs/$(ANDROID_EABI)/
303
-   cp -f $(BUILD_ROOT)/$(aStOutAnaglyph)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
304
-   cp -f $(BUILD_ROOT)/$(aStOutInterlace) $(aDestAndroid)/libs/$(ANDROID_EABI)/
305
-   cp -f $(BUILD_ROOT)/$(aStOutDistorted) $(aDestAndroid)/libs/$(ANDROID_EABI)/
306
-   cp -f $(BUILD_ROOT)/$(aStImageViewer)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
307
-   cp -f $(BUILD_ROOT)/$(aStMoviePlayer)  $(aDestAndroid)/libs/$(ANDROID_EABI)/
308
-   cp -f $(BUILD_ROOT)/$(sViewAndroidCad) $(aDestAndroid)/libs/$(ANDROID_EABI)/
309
-   cp -f $(FREETYPE_ROOT)/libs/$(ANDROID_EABI)/libfreetype.so    $(aDestAndroid)/libs/$(ANDROID_EABI)/
310
-   cp -f $(OPENAL_ROOT)/libs/$(ANDROID_EABI)/libopenal.so        $(aDestAndroid)/libs/$(ANDROID_EABI)/
311
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavcodec.so       $(aDestAndroid)/libs/$(ANDROID_EABI)/
312
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavdevice.so      $(aDestAndroid)/libs/$(ANDROID_EABI)/
313
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavformat.so      $(aDestAndroid)/libs/$(ANDROID_EABI)/
314
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavutil.so        $(aDestAndroid)/libs/$(ANDROID_EABI)/
315
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswresample.so    $(aDestAndroid)/libs/$(ANDROID_EABI)/
316
-   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswscale.so       $(aDestAndroid)/libs/$(ANDROID_EABI)/
317
+   cp -f $(BUILD_ROOT)/$(aStShared)       $(aDestAndroid)/lib/$(ANDROID_EABI)/
318
+   cp -f $(BUILD_ROOT)/$(aStGLWidgets)    $(aDestAndroid)/lib/$(ANDROID_EABI)/
319
+   cp -f $(BUILD_ROOT)/$(aStCore)         $(aDestAndroid)/lib/$(ANDROID_EABI)/
320
+   cp -f $(BUILD_ROOT)/$(aStOutAnaglyph)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
321
+   cp -f $(BUILD_ROOT)/$(aStOutInterlace) $(aDestAndroid)/lib/$(ANDROID_EABI)/
322
+   cp -f $(BUILD_ROOT)/$(aStOutDistorted) $(aDestAndroid)/lib/$(ANDROID_EABI)/
323
+   cp -f $(BUILD_ROOT)/$(aStImageViewer)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
324
+   cp -f $(BUILD_ROOT)/$(aStMoviePlayer)  $(aDestAndroid)/lib/$(ANDROID_EABI)/
325
+   cp -f $(BUILD_ROOT)/$(sViewAndroidCad) $(aDestAndroid)/lib/$(ANDROID_EABI)/
326
+   cp -f $(FREETYPE_ROOT)/libs/$(ANDROID_EABI)/libfreetype.so    $(aDestAndroid)/lib/$(ANDROID_EABI)/
327
+   cp -f $(OPENAL_ROOT)/libs/$(ANDROID_EABI)/libopenal.so        $(aDestAndroid)/lib/$(ANDROID_EABI)/
328
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavcodec.so       $(aDestAndroid)/lib/$(ANDROID_EABI)/
329
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavdevice.so      $(aDestAndroid)/lib/$(ANDROID_EABI)/
330
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavformat.so      $(aDestAndroid)/lib/$(ANDROID_EABI)/
331
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libavutil.so        $(aDestAndroid)/lib/$(ANDROID_EABI)/
332
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswresample.so    $(aDestAndroid)/lib/$(ANDROID_EABI)/
333
+   cp -f $(FFMPEG_ROOT)/libs/$(ANDROID_EABI)/libswscale.so       $(aDestAndroid)/lib/$(ANDROID_EABI)/
334
    mkdir -p $(aDestAndroid)/assets/shaders
335
    mkdir -p $(aDestAndroid)/assets/lang
336
 
337
 pre_all:
338
    mkdir -p $(BUILD_ROOT)/lang/English
339
+   mkdir -p $(BUILD_ROOT)/lang/Español
340
    mkdir -p $(BUILD_ROOT)/lang/русский
341
    mkdir -p $(BUILD_ROOT)/lang/français
342
    mkdir -p $(BUILD_ROOT)/lang/Deutsch
343
@@ -320,10 +387,13 @@
344
    mkdir -p $(BUILD_ROOT)/lang/Korean
345
    mkdir -p $(BUILD_ROOT)/textures
346
    mkdir -p $(BUILD_ROOT)/web
347
-   mkdir -p sview/libs/$(ANDROID_EABI)
348
-   mkdir -p StCADViewer/libs/$(ANDROID_EABI)
349
    cp -f -r textures/* $(BUILD_ROOT)/textures/
350
 
351
+pre_all_android:
352
+   mkdir -p $(aDestAndroid)/lib/$(ANDROID_EABI)
353
+   mkdir -p $(BUILD_ROOT)/java/gen
354
+   mkdir -p $(BUILD_ROOT)/java/classes
355
+
356
 # StShared shared library
357
 aStShared_SRCS1 := $(sort $(wildcard $(SRCDIR)/StShared/*.cpp))
358
 aStShared_OBJS1 := ${aStShared_SRCS1:.cpp=.o}
359
@@ -378,6 +448,7 @@
360
    mkdir -p $(BUILD_ROOT)/shaders/StOutAnaglyph/
361
    cp -f -r StOutAnaglyph/shaders/*      $(BUILD_ROOT)/shaders/StOutAnaglyph/
362
    cp -f -r StOutAnaglyph/lang/english/* $(BUILD_ROOT)/lang/English/
363
+   cp -f -r StOutAnaglyph/lang/spanish/* $(BUILD_ROOT)/lang/Español/
364
    cp -f -r StOutAnaglyph/lang/russian/* $(BUILD_ROOT)/lang/русский/
365
    cp -f -r StOutAnaglyph/lang/french/*  $(BUILD_ROOT)/lang/français/
366
    cp -f -r StOutAnaglyph/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
367
@@ -398,6 +469,7 @@
368
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStOutDual_OBJS) $(aStOutDual_LIB) -o $(BUILD_ROOT)/$@
369
 pre_StOutDual:
370
    cp -f -r StOutDual/lang/english/* $(BUILD_ROOT)/lang/English/
371
+   cp -f -r StOutDual/lang/spanish/* $(BUILD_ROOT)/lang/Español/
372
    cp -f -r StOutDual/lang/russian/* $(BUILD_ROOT)/lang/русский/
373
    cp -f -r StOutDual/lang/french/*  $(BUILD_ROOT)/lang/français/
374
    cp -f -r StOutDual/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
375
@@ -419,6 +491,7 @@
376
    mkdir -p $(BUILD_ROOT)/shaders/StOutIZ3D/
377
    cp -f -r StOutIZ3D/shaders/*      $(BUILD_ROOT)/shaders/StOutIZ3D/
378
    cp -f -r StOutIZ3D/lang/english/* $(BUILD_ROOT)/lang/English/
379
+   cp -f -r StOutIZ3D/lang/spanish/* $(BUILD_ROOT)/lang/Español/
380
    cp -f -r StOutIZ3D/lang/russian/* $(BUILD_ROOT)/lang/русский/
381
    cp -f -r StOutIZ3D/lang/french/*  $(BUILD_ROOT)/lang/français/
382
    cp -f -r StOutIZ3D/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
383
@@ -441,6 +514,7 @@
384
    mkdir -p $(BUILD_ROOT)/shaders/StOutInterlace/
385
    cp -f -r StOutInterlace/shaders/*      $(BUILD_ROOT)/shaders/StOutInterlace/
386
    cp -f -r StOutInterlace/lang/english/* $(BUILD_ROOT)/lang/English/
387
+   cp -f -r StOutInterlace/lang/spanish/* $(BUILD_ROOT)/lang/Español/
388
    cp -f -r StOutInterlace/lang/russian/* $(BUILD_ROOT)/lang/русский/
389
    cp -f -r StOutInterlace/lang/french/*  $(BUILD_ROOT)/lang/français/
390
    cp -f -r StOutInterlace/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
391
@@ -467,6 +541,7 @@
392
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStOutPageFlip_OBJS1) $(aStOutPageFlip_OBJS2) $(aStOutPageFlip_LIB) -o $(BUILD_ROOT)/$@
393
 pre_StOutPageFlip:
394
    cp -f -r StOutPageFlip/lang/english/* $(BUILD_ROOT)/lang/English/
395
+   cp -f -r StOutPageFlip/lang/spanish/* $(BUILD_ROOT)/lang/Español/
396
    cp -f -r StOutPageFlip/lang/russian/* $(BUILD_ROOT)/lang/русский/
397
    cp -f -r StOutPageFlip/lang/french/*  $(BUILD_ROOT)/lang/français/
398
    cp -f -r StOutPageFlip/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
399
@@ -486,6 +561,7 @@
400
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStOutDistorted_OBJS) $(aStOutDistorted_LIB) -o $(BUILD_ROOT)/$@
401
 pre_StOutDistorted:
402
    cp -f -r StOutDistorted/lang/english/* $(BUILD_ROOT)/lang/English/
403
+   cp -f -r StOutDistorted/lang/spanish/* $(BUILD_ROOT)/lang/Español/
404
    cp -f -r StOutDistorted/lang/russian/* $(BUILD_ROOT)/lang/русский/
405
    cp -f -r StOutDistorted/lang/french/*  $(BUILD_ROOT)/lang/français/
406
    cp -f -r StOutDistorted/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
407
@@ -505,6 +581,7 @@
408
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStImageViewer_OBJS) $(aStImageViewer_LIB) -o $(BUILD_ROOT)/$@
409
 pre_StImageViewer:
410
    cp -f -r StImageViewer/lang/english/* $(BUILD_ROOT)/lang/English/
411
+   cp -f -r StImageViewer/lang/spanish/* $(BUILD_ROOT)/lang/Español/
412
    cp -f -r StImageViewer/lang/russian/* $(BUILD_ROOT)/lang/русский/
413
    cp -f -r StImageViewer/lang/french/*  $(BUILD_ROOT)/lang/français/
414
    cp -f -r StImageViewer/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
415
@@ -523,11 +600,12 @@
416
 aStMoviePlayer_OBJS2 := ${aStMoviePlayer_SRCS2:.cpp=.o}
417
 aStMoviePlayer_SRCS3 := $(sort $(wildcard $(SRCDIR)/StMoviePlayer/*.c))
418
 aStMoviePlayer_OBJS3 := ${aStMoviePlayer_SRCS3:.c=.o}
419
-aStMoviePlayer_LIB   := $(LIB) -lStGLWidgets -lStShared -lStCore $(LIB_OUTPUTS) $(LIB_GLX) $(LIB_GTK) -lavutil -lavformat -lavcodec -lswscale $(LIB_OPENAL) $(LIB_PTHREAD)
420
+aStMoviePlayer_LIB   := $(LIB) -lStGLWidgets -lStShared -lStCore $(LIB_OUTPUTS) $(LIB_GLX) $(LIB_GTK) -lavutil -lavformat -lavcodec -lswscale $(LIB_OPENAL) $(LIB_COREVIDEO) $(LIB_PTHREAD)
421
 $(aStMoviePlayer) : pre_StMoviePlayer $(aStGLWidgets) outputs_all $(aStMoviePlayer_OBJS1) $(aStMoviePlayer_OBJS2) $(aStMoviePlayer_OBJS3)
422
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStMoviePlayer_OBJS1) $(aStMoviePlayer_OBJS2) $(aStMoviePlayer_OBJS3) $(aStMoviePlayer_LIB) -o $(BUILD_ROOT)/$@
423
 pre_StMoviePlayer:
424
    cp -f -r StMoviePlayer/lang/english/* $(BUILD_ROOT)/lang/English/
425
+   cp -f -r StMoviePlayer/lang/spanish/* $(BUILD_ROOT)/lang/Español/
426
    cp -f -r StMoviePlayer/lang/russian/* $(BUILD_ROOT)/lang/русский/
427
    cp -f -r StMoviePlayer/lang/french/*  $(BUILD_ROOT)/lang/français/
428
    cp -f -r StMoviePlayer/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
429
@@ -550,6 +628,7 @@
430
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStDiagnostics_OBJS) $(aStDiagnostics_LIB) -o $(BUILD_ROOT)/$@
431
 pre_StDiagnostics:
432
    cp -f -r StDiagnostics/lang/english/* $(BUILD_ROOT)/lang/English/
433
+   cp -f -r StDiagnostics/lang/spanish/* $(BUILD_ROOT)/lang/Español/
434
    cp -f -r StDiagnostics/lang/russian/* $(BUILD_ROOT)/lang/русский/
435
    cp -f -r StDiagnostics/lang/french/*  $(BUILD_ROOT)/lang/français/
436
    cp -f -r StDiagnostics/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
437
@@ -581,6 +660,7 @@
438
    $(LD) -shared $(call libinstname,$@) $(LDFLAGS) $(LIBDIR) $(aStCADViewer_OBJS) $(aStCADViewer_LIB) -o $(BUILD_ROOT)/$@
439
 pre_StCADViewer:
440
    cp -f -r StCADViewer/lang/english/* $(BUILD_ROOT)/lang/English/
441
+   cp -f -r StCADViewer/lang/spanish/* $(BUILD_ROOT)/lang/Español/
442
    cp -f -r StCADViewer/lang/russian/* $(BUILD_ROOT)/lang/русский/
443
    cp -f -r StCADViewer/lang/french/*  $(BUILD_ROOT)/lang/français/
444
    cp -f -r StCADViewer/lang/german/*  $(BUILD_ROOT)/lang/Deutsch/
445
@@ -601,6 +681,14 @@
446
 clean_sViewAndroid:
447
    rm -f $(BUILD_ROOT)/$(sViewAndroid)
448
    rm -rf sview/jni/*.o
449
+   rm -rf $(BUILD_ROOT)/java/classes/com/sview/*.class
450
+   rm -rf $(SRCDIR)/sview/src/com/sview/*class
451
+   rm -rf $(aDestAndroid)
452
+   rm -f $(sViewDex)
453
+   rm -f $(sViewApkUnsigned)
454
+   rm -f $(sViewApkSigned)
455
+   rm -f $(sViewApk)
456
+   rm -rf $(BUILD_ROOT)/java/gen/com/sview/*.java
457
 
458
 # sView executable
459
 sView_SRCS1 := $(sort $(wildcard $(SRCDIR)/sview/*.cpp))
460
@@ -635,11 +723,57 @@
461
    cp -R -f $(FFMPEG_ROOT)/$(LIBSUBFOLDER)/libswscale*.dylib    $(BUILD_ROOT_BUNDLE)/Contents/Frameworks
462
 endif
463
 ifneq ($(OPENAL_ROOT),)
464
+   mkdir -p $(BUILD_ROOT_BUNDLE)/Contents/MacOS/openal/hrtf/
465
    cp -R -f $(OPENAL_ROOT)/$(LIBSUBFOLDER)/libopenal*.dylib     $(BUILD_ROOT_BUNDLE)/Contents/Frameworks
466
+   cp -f -r $(OPENAL_ROOT)/hrtf/*.mhr                           $(BUILD_ROOT_BUNDLE)/Contents/MacOS/openal/hrtf/
467
 endif
468
 endif
469
    @echo sView building is DONE
470
 
471
+$(sViewApk): $(sViewApkSigned)
472
+   $(ANDROID_BUILD_TOOLS)/zipalign -v -f 4 $< $(sViewApk)
473
+
474
+# There are three options:
475
+# 1) Passwords are specified within Makefile / passed as make arguments
476
+# 2) Passwords are asked by jarsigner itself (requires console input)
477
+# 3) Passwords are asked using zenity message window (requires GUI input)
478
+ifeq ($(MAKECMDGOALS), android)
479
+
480
+ifeq ($(ANDROID_KEY_GUI), 1)
481
+$(sViewApkSigned): $(sViewApkUnsigned) sView_keystore_debug
482
+   $(eval ANDROID_KEYSTORE_PASSWORD := $(shell zenity --password --title="Android keystore"))
483
+   $(eval ANDROID_KEY_PASSWORD      := $(shell zenity --password --title="Android key"))
484
+   $(JAVA_HOME)/bin/jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $(ANDROID_KEYSTORE) -storepass $(ANDROID_KEYSTORE_PASSWORD) -keypass $(ANDROID_KEY_PASSWORD) -signedjar $(sViewApkSigned) $< $(ANDROID_KEY)
485
+else ifeq ($(ANDROID_KEY_PASSWORD),)
486
+$(sViewApkSigned): $(sViewApkUnsigned) sView_keystore_debug
487
+   $(JAVA_HOME)/bin/jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $(ANDROID_KEYSTORE) -signedjar $(sViewApkSigned) $< $(ANDROID_KEY)
488
+else
489
+$(sViewApkSigned): $(sViewApkUnsigned) sView_keystore_debug
490
+   $(JAVA_HOME)/bin/jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $(ANDROID_KEYSTORE) -storepass $(ANDROID_KEYSTORE_PASSWORD) -keypass $(ANDROID_KEY_PASSWORD) -signedjar $(sViewApkSigned) $< $(ANDROID_KEY)
491
+endif
492
+endif
493
+
494
+$(sViewApkUnsigned): $(sViewDex) install_android_libs
495
+   rm -f $(sViewApkUnsigned)
496
+   $(ANDROID_BUILD_TOOLS)/aapt package -v -f -M $(SRCDIR)/sview/AndroidManifest.xml -S $(SRCDIR)/sview/res -I $(ANDROID_PLATFORM) -F $(sViewApkUnsigned) $(aDestAndroid)
497
+
498
+sView_SRCS_JAVA1 := $(sort $(wildcard $(SRCDIR)/sview/src/com/sview/*.java))
499
+sView_OBJS_JAVA1 := ${sView_SRCS_JAVA1:.java=.class}
500
+$(sViewDex): $(BUILD_ROOT)/java/gen/com/sview/R.class $(sView_OBJS_JAVA1)
501
+   $(ANDROID_BUILD_TOOLS)/dx --dex --verbose --output=$(sViewDex) $(BUILD_ROOT)/java/classes
502
+
503
+$(BUILD_ROOT)/java/gen/com/sview/R.java: install_android $(shell find $(SRCDIR)/sview/res -type f)
504
+   $(ANDROID_BUILD_TOOLS)/aapt package -v -f -m -S $(SRCDIR)/sview/res -J $(BUILD_ROOT)/java/gen -M $(SRCDIR)/sview/AndroidManifest.xml -I $(ANDROID_PLATFORM)
505
+
506
+# This target generates a dummy signing key for debugging purposes.
507
+# Executed only when ANDROID_KEYSTORE points to non-existing file.
508
+ifeq (,$(wildcard $(ANDROID_KEYSTORE)))
509
+sView_keystore_debug:
510
+   $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=sview_dummy,O=Android,C=JPN" -keystore $(ANDROID_KEYSTORE) \
511
+   -storepass $(ANDROID_KEYSTORE_PASSWORD) -keypass $(ANDROID_KEY_PASSWORD) -alias $(ANDROID_KEY) -keyalg RSA -v
512
+else
513
+sView_keystore_debug:
514
+endif
515
 
516
 clean_sView:
517
    rm -f $(BUILD_ROOT)/$(sView)
518
sview-17_04.tar.gz/StBrowserPlugin/StBrowserPlugin.rc -> sview-20_08.tar.gz/StBrowserPlugin/StBrowserPlugin.rc Changed
10
 
1
@@ -21,7 +21,7 @@
2
       VALUE "FileOpenName",     ST_NPAPI_MIME_DESC
3
       VALUE "FileVersion",      SVIEW_SDK_VER_STRING "\000"
4
       VALUE "InternalName",     "StBrowserPlugin\000"
5
-      VALUE "LegalCopyright",   "\251 2009-2016 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",   "\251 2009-2020 Kirill Gavrilov\000"
7
       VALUE "LegalTrademarks",  "\000"
8
       VALUE "MIMEType",         ST_NPAPI_MIME_LIST
9
       VALUE "OriginalFilename", "npStBrowserPlugin.dll\000"
10
sview-17_04.tar.gz/StCADViewer/StCADViewer.rc -> sview-20_08.tar.gz/StCADViewer/StCADViewer.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereoscopic CAD Viewer\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2011-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2011-2020 Kirill Gavrilov\000"
7
       VALUE "ProductName",     "StCADViewer\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StCADViewer/StCADViewerGUI.cpp -> sview-20_08.tar.gz/StCADViewer/StCADViewerGUI.cpp Changed
10
 
1
@@ -426,7 +426,7 @@
2
     const StGLVec3 THE_WHITE(1.0f, 1.0f, 1.0f);
3
     const StString anAbout = tr(ABOUT_DPLUGIN_NAME) + '\n'
4
                            + tr(ABOUT_VERSION) + " " + StVersionInfo::getSDKVersionString()
5
-                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2011-2017", "kirill@sview.ru", "www.sview.ru");
6
+                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2011-2020", "kirill@sview.ru", "www.sview.ru");
7
 
8
     StArgumentsMap anInfo;
9
     anInfo.add(StDictEntry("CPU cores", StString(StThread::countLogicalProcessors()) + StString(" logical processor(s)")));
10
sview-20_08.tar.gz/StCADViewer/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StCADViewer/lang/spanish/StCADViewer.lng Added
29
 
1
@@ -0,0 +1,27 @@
2
+# Spanish translation file for StCADViewer
3
+--------
4
+1200=Ver
5
+1202=Pantalla completa
6
+1204=Mostrar triedro
7
+1206=Proyección
8
+1208=Ajustar TODO
9
+1240=Ortogonal
10
+1241=Perspectiva
11
+1242=Estéreo
12
+1402=Mostrar FPS
13
+1500=Ayuda
14
+1501=Acerca de...
15
+1503=Texto de la licencia
16
+1504=Idioma (Language)
17
+1511=Ajustes
18
+3000=sView - Mini visor de CAD
19
+3001=versión
20
+3002=El visualizador CAD te permite ver archivos CAD en formatos IGES, STEP y BREP usando tecnología OpenCASCADE.\n © {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}\n\nEste programa se distribuye bajo licencia GPL 3.0
21
+3004=Información del sistema
22
+4000=Cerrar
23
+4001=Cancelar
24
+4006=Guardar
25
+4007=Eliminar
26
+4008=Predeterminado
27
+4009=Predeterminados
28
+4010=Asignar
29
sview-17_04.tar.gz/StCore/StAndroidGlue.cpp -> sview-20_08.tar.gz/StCore/StAndroidGlue.cpp Changed
262
 
1
@@ -19,60 +19,13 @@
2
 #include <StStrings/StLogger.h>
3
 
4
 #include <StAV/stAV.h>
5
+#include <StJNI/StJNIEnv.h>
6
 
7
 #include <android/window.h>
8
 
9
-#define jexp extern "C" JNIEXPORT
10
-
11
-StJNIEnv::StJNIEnv(JavaVM* theJavaVM)
12
-: myJavaVM(theJavaVM),
13
-  myJniEnv(NULL),
14
-  myToDetach(false) {
15
-    if(myJavaVM == NULL) {
16
-        return;
17
-    }
18
-
19
-    void* aJniEnv = NULL;
20
-    switch(myJavaVM->GetEnv(&aJniEnv, JNI_VERSION_1_6)) {
21
-        case JNI_EDETACHED: {
22
-            if(myJavaVM->AttachCurrentThread(&myJniEnv, NULL) < 0) {
23
-                myJniEnv = NULL;
24
-                ST_ERROR_LOG("Failed to attach working thread to Java VM");
25
-                return;
26
-            }
27
-            myToDetach = true;
28
-            break;
29
-        }
30
-        case JNI_OK: {
31
-            myJniEnv   = (JNIEnv* )aJniEnv;
32
-            myToDetach = false;
33
-            break;
34
-        }
35
-        case JNI_EVERSION: {
36
-            ST_ERROR_LOG("Failed to attach working thread to Java VM - JNI version is not supported");
37
-            break;
38
-        }
39
-        default: {
40
-            ST_ERROR_LOG("Failed to attach working thread to Java VM");
41
-            break;
42
-        }
43
-    }
44
-}
45
-
46
-StJNIEnv::~StJNIEnv() {
47
-    detach();
48
-}
49
+#include "stvkeysandroid.h" // Android NDK keys to VKEYs lookup array
50
 
51
-void StJNIEnv::detach() {
52
-    if(myJavaVM != NULL
53
-    && myJniEnv != NULL
54
-    && myToDetach) {
55
-        myJavaVM->DetachCurrentThread();
56
-    }
57
-
58
-    myJniEnv   = NULL;
59
-    myToDetach = false;
60
-}
61
+#define jexp extern "C" JNIEXPORT
62
 
63
 StAndroidResourceManager::StAndroidResourceManager(StAndroidGlue*  theGlueApp,
64
                                                    const StString& theAppName)
65
@@ -171,6 +124,7 @@
66
   myWindow(NULL),
67
   myWindowPending(NULL),
68
   myIsChangingSurface(false),
69
+  myIsWakeLockSet(false),
70
   myWindowFlags(0),
71
   myActivityState(0),
72
   myMemoryClassMiB(0),
73
@@ -190,6 +144,7 @@
74
   myIsRunning(false),
75
   myIsStateSaved(false),
76
   myToDestroy(false) {
77
+    stMemZero(myRegKeys, sizeof(myRegKeys));
78
     theActivity->instance = this;
79
     theActivity->env->GetJavaVM(&myJavaVM);
80
 
81
@@ -210,6 +165,15 @@
82
         myMemoryClassMiB = aJniEnv->CallIntMethod(aJActivityMgr, aJMet_getMemoryClass);
83
     }
84
 
85
+    if(jclass aClassBuild = aJniEnv->FindClass("android/os/Build")) {
86
+        if(jfieldID aJFieldModel = aJniEnv->GetStaticFieldID(aClassBuild, "MODEL", "Ljava/lang/String;")) {
87
+            myBuildModel = stStringFromJava(aJniEnv, (jstring )aJniEnv->GetStaticObjectField(aClassBuild, aJFieldModel));
88
+        }
89
+        if(jfieldID aJFieldDevice = aJniEnv->GetStaticFieldID(aClassBuild, "DEVICE", "Ljava/lang/String;")) {
90
+            myBuildDevice = stStringFromJava(aJniEnv, (jstring )aJniEnv->GetStaticObjectField(aClassBuild, aJFieldDevice));
91
+        }
92
+    }
93
+
94
     jmethodID aJMet_getStAppClass = aJniEnv->GetMethodID(aJClass_Activity, "getStAppClass", "()Ljava/lang/String;");
95
     myStAppClass = stStringFromJava(aJniEnv, (jstring )aJniEnv->CallObjectMethod(myActivity->clazz, aJMet_getStAppClass));
96
 
97
@@ -220,7 +184,8 @@
98
     jmethodID aJMet_setCppInstance = aJniEnv->GetMethodID(aJClass_Activity, "setCppInstance", "(J)V");
99
     aJniEnv->CallVoidMethod(myActivity->clazz, aJMet_setCppInstance, (jlong )this);
100
 
101
-    readOpenPath();
102
+    // do not NULLify intent here since Activity.onCreate() crashes on some devices
103
+    readOpenPath(false);
104
 
105
     myCmdPollSource.id        = LooperId_MAIN;
106
     myCmdPollSource.app       = this;
107
@@ -261,11 +226,11 @@
108
     myMsgWrite = aMsgPipe[1];
109
 }
110
 
111
-void StAndroidGlue::readOpenPath() {
112
+void StAndroidGlue::readOpenPath(bool theToNullifyIntent) {
113
     JNIEnv*   aJniEnv = myActivity->env;
114
     jclass    aJClass_Activity   = aJniEnv->GetObjectClass(myActivity->clazz);
115
-    jmethodID aJMet_readOpenPath = aJniEnv->GetMethodID(aJClass_Activity, "readOpenPath", "()V");
116
-    aJniEnv->CallVoidMethod(myActivity->clazz, aJMet_readOpenPath);
117
+    jmethodID aJMet_readOpenPath = aJniEnv->GetMethodID(aJClass_Activity, "readOpenPath", "(Z)V");
118
+    aJniEnv->CallVoidMethod(myActivity->clazz, aJMet_readOpenPath, (jboolean )(theToNullifyIntent ? JNI_TRUE : JNI_FALSE));
119
 }
120
 
121
 void StAndroidGlue::setOpenPath(const jstring  theOpenPath,
122
@@ -295,8 +260,11 @@
123
 
124
 void StAndroidGlue::fetchState(StString&             theNewFile,
125
                                StQuaternion<double>& theQuaternion,
126
-                               bool&                 theToSwapEyes) {
127
+                               bool&                 theToSwapEyes,
128
+                               const StKeysState&    theKeys) {
129
     StMutexAuto aLock(myFetchLock);
130
+    stMemCpy(myRegKeys, theKeys.getRegisteredKeys(), sizeof(myRegKeys));
131
+
132
     theQuaternion = myQuaternion;
133
     theToSwapEyes = myToSwapEyesHW;
134
     if(!myDndPath.isEmpty()) {
135
@@ -376,8 +344,17 @@
136
 
137
     StMonitor aMon;
138
     aMon.setId(0);
139
+
140
+    const StString aBuildDevice = myBuildDevice.lowerCased();
141
+    const StString aBuildModel  = myBuildModel.lowerCased();
142
     if(myStereoApiId == "S3DV") {
143
         aMon.setPnPId("ST@S3DV");
144
+    } else if(aBuildDevice == "king7s" || aBuildModel == "pp6000") { // PPTV King 7S
145
+        aMon.setPnPId("ST@COL0");
146
+    } else if(aBuildModel == "y6 max 3d") { // DOOGEE Y6 Max 3D
147
+        aMon.setPnPId("ST@COL0");
148
+    } else if(aBuildModel == "p8 3d" || aBuildModel == "p8_3d") { // Elephone P8 3D
149
+        aMon.setPnPId("ST@COL0");
150
     }
151
     aMon.changeVRect().top()    = 0;
152
     aMon.changeVRect().left()   = 0;
153
@@ -523,14 +500,26 @@
154
         postMessage("jp.co.sharp.android.stereo3dlcd !!!");
155
     }*/
156
 
157
-    createApplication();
158
-    if(!myApp.isNull()) {
159
-        if(!myApp->open()) {
160
+    for(;;) {
161
+        createApplication();
162
+        if(myApp.isNull()) {
163
+            stError("Error: no application to execute!");
164
+            break;
165
+        } else if(!myApp->open()) {
166
             stError("Error: application can not be executed!");
167
+            break;
168
         }
169
         myApp->exec();
170
-    } else {
171
-        stError("Error: no application to execute!");
172
+
173
+        StHandle<StOpenInfo> anOther = myApp->getOpenFileInOtherDrawer();
174
+        if(anOther.isNull()) {
175
+            break;
176
+        }
177
+
178
+        myApp.nullify();
179
+        StArgument aDrawerArg = anOther->getArgumentsMap()["in"];
180
+        myDndPath = anOther->getPath();
181
+        myStAppClass = aDrawerArg.getValue();
182
     }
183
     myApp.nullify();
184
 
185
@@ -767,7 +756,7 @@
186
 
187
 void StAndroidGlue::setActivityState(int8_t theState) {
188
     if(theState == StAndroidGlue::CommandId_Resume) {
189
-        readOpenPath();
190
+        readOpenPath(true);
191
     }
192
 
193
     pthread_mutex_lock(&myMutex);
194
@@ -834,6 +823,36 @@
195
     ANativeActivity_setWindowFlags(myActivity, aFlagsToAdd, aFlagsToRemove);
196
 }
197
 
198
+void StAndroidGlue::setWakeLock(const StString& theTitle, bool theToLock) {
199
+    if((myIsWakeLockSet == theToLock
200
+     && myWakeLockTitle == theTitle)
201
+    || myThJniEnv == NULL) {
202
+        return;
203
+    }
204
+
205
+    jclass    aJClassActivity = myThJniEnv->GetObjectClass(myActivity->clazz);
206
+    jmethodID aJMet           = myThJniEnv->GetMethodID(aJClassActivity, "setPartialWakeLockOn", "(Ljava/lang/String;Z)V");
207
+    jstring   aJStrTitle      = myThJniEnv->NewStringUTF(theTitle.toCString());
208
+    myThJniEnv->CallVoidMethod(myActivity->clazz, aJMet, aJStrTitle, (jboolean )(theToLock ? JNI_TRUE : JNI_FALSE));
209
+    myIsWakeLockSet = theToLock;
210
+    myThJniEnv->DeleteLocalRef(aJStrTitle);
211
+    myWakeLockTitle = theTitle;
212
+}
213
+
214
+void StAndroidGlue::setWindowTitle(const StString& theTitle) {
215
+    if(myWindowTitle == theTitle
216
+    || myThJniEnv == NULL) {
217
+        return;
218
+    }
219
+
220
+    jclass    aJClassActivity = myThJniEnv->GetObjectClass(myActivity->clazz);
221
+    jmethodID aJMet           = myThJniEnv->GetMethodID(aJClassActivity, "setWindowTitle", "(Ljava/lang/String;)V");
222
+    jstring   aJStrTitle      = myThJniEnv->NewStringUTF(theTitle.toCString());
223
+    myThJniEnv->CallVoidMethod(myActivity->clazz, aJMet, aJStrTitle);
224
+    myThJniEnv->DeleteLocalRef(aJStrTitle);
225
+    myWindowTitle = theTitle;
226
+}
227
+
228
 void StAndroidGlue::setHardwareStereoOn(const bool theToEnable) {
229
     if(myToEnableStereoHW == theToEnable
230
     || myStereoApiId.isEmpty()
231
@@ -905,6 +924,20 @@
232
     myToSwapEyesHW = theToSwapLR;
233
 }
234
 
235
+bool StAndroidGlue::isKeyOverridden(int theKeyCode) {
236
+    StVirtKey aVKeySt = ST_VK_NULL;
237
+    if(theKeyCode < ST_ANDROID2ST_VK_SIZE) {
238
+        aVKeySt = (StVirtKey )ST_ANDROID2ST_VK[theKeyCode];
239
+    }
240
+
241
+    if(aVKeySt <= 0 || (int )aVKeySt >= ST_VK_NB) {
242
+        return false;
243
+    }
244
+
245
+    StMutexAuto aLock(myFetchLock);
246
+    return myRegKeys[aVKeySt];
247
+}
248
+
249
 jexp void JNICALL Java_com_sview_StActivity_cppSetOpenPath(JNIEnv* theEnv, jobject theObj, jlong theCppPtr,
250
                                                            jstring theOpenPath, jstring theMimeType, jboolean theIsLaunchedFromHistory) {
251
     ((StAndroidGlue* )theCppPtr)->setOpenPath(theOpenPath, theMimeType, theIsLaunchedFromHistory);
252
@@ -940,4 +973,9 @@
253
     ((StAndroidGlue* )theCppPtr)->setSwapEyes(theToSwap == JNI_TRUE);
254
 }
255
 
256
+jexp jboolean JNICALL Java_com_sview_StActivity_cppIsKeyOverridden(JNIEnv* theEnv, jobject theObj, jlong theCppPtr,
257
+                                                                   jint theKeyCode) {
258
+    return ((StAndroidGlue* )theCppPtr)->isKeyOverridden(theKeyCode);
259
+}
260
+
261
 #endif // __ANDROID__
262
sview-17_04.tar.gz/StCore/StApplication.cpp -> sview-20_08.tar.gz/StCore/StApplication.cpp Changed
137
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StCore, window system independent C++ toolkit for writing OpenGL applications.
4
- * Copyright © 2009-2016 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -21,9 +21,42 @@
10
 #include "StEventsBuffer.h"
11
 
12
 namespace {
13
+
14
     static const StCString ST_SETTING_RENDERER_AUTO = stCString("rendererPluginAuto");
15
     static const StCString ST_SETTING_RENDERER      = stCString("rendererPlugin");
16
     static const StCString ST_SETTING_AUTO_VALUE    = stCString("Auto");
17
+    static const StCString ST_SETTING_DEF_DRAWER    = stCString("defaultDrawer");
18
+
19
+    /**
20
+     * Auxiliary parameter.
21
+     */
22
+    class StDefaultDrawerParam : public StBoolParamNamed {
23
+
24
+            public:
25
+
26
+        /**
27
+         * Main constructor.
28
+         */
29
+        StDefaultDrawerParam(const StApplication* theApp, const StString& theDrawer, const StString& theTitle)
30
+        : StBoolParamNamed(theApp->isDefaultDrawer(theDrawer), StString(), theTitle),
31
+          myApp(theApp), myAppName(theDrawer) {}
32
+
33
+        /**
34
+         * Return list of available translations.
35
+         */
36
+        virtual bool setValue(const bool theValue) ST_ATTR_OVERRIDE {
37
+            const bool aResult = StBoolParamNamed::setValue(theValue);
38
+            myApp->setDefaultDrawer(theValue ? myAppName : StString());
39
+            return aResult;
40
+        }
41
+
42
+            private:
43
+
44
+        const StApplication* myApp;
45
+        StString myAppName;
46
+
47
+    };
48
+
49
 }
50
 
51
 void StApplication::doChangeDevice(const int32_t theValue) {
52
@@ -364,22 +397,32 @@
53
 
54
 void StApplication::registerHotKeys() {
55
     myKeyActions.clear();
56
+    StKeysState* aKeysState = !myWindow.isNull() ? &myWindow->changeKeysState() : NULL;
57
+    if(aKeysState != NULL) {
58
+        aKeysState->resetRegisteredKeys();
59
+    }
60
     for(std::map< int, StHandle<StAction> >::iterator anIter = myActions.begin();
61
         anIter != myActions.end(); ++anIter) {
62
         const StHandle<StAction>& anAction = anIter->second;
63
-        if(anAction->getHotKey1() != 0) {
64
-            StHandle<StAction> anOldAction = getActionForKey(anAction->getHotKey1());
65
-            if(!anOldAction.isNull()) {
66
-                anOldAction->setHotKey1(0);
67
+        for(int aHotIter = 0; aHotIter < 2; ++aHotIter) {
68
+            const unsigned int aHotKey = anAction->getHotKey(aHotIter);
69
+            if(aHotKey == 0) {
70
+                continue;
71
             }
72
-            myKeyActions[anAction->getHotKey1()] = anAction;
73
-        }
74
-        if(anAction->getHotKey2() != 0) {
75
-            StHandle<StAction> anOldAction = getActionForKey(anAction->getHotKey2());
76
+
77
+            StHandle<StAction> anOldAction = getActionForKey(aHotKey);
78
             if(!anOldAction.isNull()) {
79
-                anOldAction->setHotKey2(0);
80
+                for(int anOldHotIter = 0; anOldHotIter < 2; ++anOldHotIter) {
81
+                    if(anOldAction->getHotKey(anOldHotIter) == aHotKey) {
82
+                        anOldAction->setHotKey(anOldHotIter, 0);
83
+                    }
84
+                }
85
+            }
86
+            myKeyActions[aHotKey] = anAction;
87
+            if(aKeysState != NULL) {
88
+                const StVirtKey aVirtKey = getBaseKeyFromHotKey(aHotKey);
89
+                aKeysState->registerKey(aVirtKey);
90
             }
91
-            myKeyActions[anAction->getHotKey2()] = anAction;
92
         }
93
     }
94
 }
95
@@ -556,6 +599,41 @@
96
     return anInfo;
97
 }
98
 
99
+bool StApplication::isDefaultDrawer(const StString& theDrawer) const {
100
+    StSettings aGlobalSettings(myResMgr, "sview");
101
+    StString aDefDrawer;
102
+    aGlobalSettings.loadString(ST_SETTING_DEF_DRAWER, aDefDrawer);
103
+    return theDrawer == aDefDrawer;
104
+}
105
+
106
+void StApplication::setDefaultDrawer(const StString& theDrawer) const {
107
+    StSettings aGlobalSettings(myResMgr, "sview");
108
+    aGlobalSettings.saveString(ST_SETTING_DEF_DRAWER, theDrawer);
109
+}
110
+
111
+bool StApplication::readDefaultDrawer(StHandle<StOpenInfo>& theInfo) {
112
+    StHandle<StResourceManager> aResMgr = new StResourceManager();
113
+    StSettings aGlobalSettings(aResMgr, "sview");
114
+    StString aDefDrawer;
115
+    aGlobalSettings.loadString(ST_SETTING_DEF_DRAWER, aDefDrawer);
116
+    if(aDefDrawer.isEmpty()) {
117
+        return false;
118
+    }
119
+
120
+    if(theInfo.isNull()) {
121
+        theInfo = new StOpenInfo();
122
+    }
123
+    StArgumentsMap anArgs = theInfo->getArgumentsMap();
124
+    anArgs.add(StArgument("in", aDefDrawer));
125
+    theInfo->setArgumentsMap(anArgs);
126
+    return true;
127
+}
128
+
129
+StHandle<StBoolParamNamed> StApplication::createDefaultDrawerParam(const StString& theDrawer,
130
+                                                                   const StString& theTitle) const {
131
+    return new StDefaultDrawerParam(this, theDrawer, theTitle);
132
+}
133
+
134
 void StApplication::doChangeLanguage(const int32_t ) {
135
     myToRecreateMenu = true;
136
     myLangMap->resetReloaded();
137
sview-17_04.tar.gz/StCore/StCocoaView.h -> sview-20_08.tar.gz/StCore/StCocoaView.h Changed
17
 
1
@@ -20,6 +20,7 @@
2
 
3
     class StWindowImpl;
4
 
5
+ST_DISABLE_DEPRECATION_WARNINGS
6
     @interface StCocoaView : NSOpenGLView
7
     {
8
         StWindowImpl* myStWin;        //!< pointer to StWindowImpl instance
9
@@ -33,6 +34,7 @@
10
         bool          myToHideCursor;
11
         bool          myIsLionOS;
12
     }
13
+ST_ENABLE_DEPRECATION_WARNINGS
14
 
15
         /**
16
          * Main constructor.
17
sview-17_04.tar.gz/StCore/StCocoaView.mm -> sview-20_08.tar.gz/StCore/StCocoaView.mm Changed
44
 
1
@@ -50,8 +50,10 @@
2
     - (id ) initWithStWin: (StWindowImpl* ) theStWin
3
                     nsWin: (NSWindow* )     theNsWin {
4
         NSRect aBounds = [[theNsWin contentView] bounds];
5
+    ST_DISABLE_DEPRECATION_WARNINGS
6
         self = [super initWithFrame: aBounds
7
                         pixelFormat: [[NSOpenGLView class] defaultPixelFormat]];
8
+    ST_ENABLE_DEPRECATION_WARNINGS
9
         if(self == NULL) {
10
             return NULL;
11
         }
12
@@ -62,7 +64,9 @@
13
 
14
         // enable HiDPI mode
15
         if(myIsLionOS) {
16
+        ST_DISABLE_DEPRECATION_WARNINGS
17
             [self setWantsBestResolutionOpenGLSurface: YES];
18
+        ST_ENABLE_DEPRECATION_WARNINGS
19
         }
20
 
21
         // create blank cursor
22
@@ -348,17 +352,17 @@
23
         CGFloat aDeltaY = [theEvent deltaY];
24
         if(!stAreEqual(aDeltaX, 0.0f, 0.01f)) {
25
             myStEvent.Scroll.StepsX = aDeltaX > 0.0f ? -1 :  1;
26
-            myStEvent.Scroll.DeltaX = 10.0f * myStEvent.Scroll.StepsX;
27
+            myStEvent.Scroll.DeltaX = myStEvent.Scroll.StepsX;
28
         }
29
         if(!stAreEqual(aDeltaY, 0.0f, 0.01f)) {
30
             myStEvent.Scroll.StepsY = aDeltaY > 0.0f ?  1 : -1;
31
-            myStEvent.Scroll.DeltaY = 10.0f * myStEvent.Scroll.StepsY;
32
+            myStEvent.Scroll.DeltaY = myStEvent.Scroll.StepsY;
33
         }
34
 
35
         if(myIsLionOS
36
         && [theEvent hasPreciseScrollingDeltas]) {
37
-            myStEvent.Scroll.DeltaX = [theEvent scrollingDeltaX];
38
-            myStEvent.Scroll.DeltaY = [theEvent scrollingDeltaY];
39
+            myStEvent.Scroll.DeltaX = 0.1f * [theEvent scrollingDeltaX];
40
+            myStEvent.Scroll.DeltaY = 0.1f * [theEvent scrollingDeltaY];
41
         }
42
 
43
         //if([theEvent subtype] == NSMouseEventSubtype) {
44
sview-17_04.tar.gz/StCore/StCore.rc -> sview-20_08.tar.gz/StCore/StCore.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "sView core library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StCore\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StCore/StKeysState.cpp -> sview-20_08.tar.gz/StCore/StKeysState.cpp Changed
37
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StCore, window system independent C++ toolkit for writing OpenGL applications.
4
- * Copyright © 2013 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -10,13 +10,26 @@
10
 #include <StCore/StKeysState.h>
11
 
12
 StKeysState::StKeysState() {
13
-    stMemZero(myKeys, sizeof(myKeys));
14
+    stMemZero(myKeys,    sizeof(myKeys));
15
+    stMemZero(myRegKeys, sizeof(myRegKeys));
16
 }
17
 
18
 StKeysState::~StKeysState() {
19
     //
20
 }
21
 
22
+void StKeysState::resetRegisteredKeys() {
23
+    stMemZero(myRegKeys, sizeof(myRegKeys));
24
+}
25
+
26
+void StKeysState::registerKey(StVirtKey theKey) {
27
+    myRegKeys[theKey] = true;
28
+}
29
+
30
+void StKeysState::unregisterKey(StVirtKey theKey) {
31
+    myRegKeys[theKey] = false;
32
+}
33
+
34
 void StKeysState::reset() {
35
     StMutexAuto aLock(myLock);
36
     stMemZero(myKeys, sizeof(myKeys));
37
sview-17_04.tar.gz/StCore/StSearchMonitors.cpp -> sview-20_08.tar.gz/StCore/StSearchMonitors.cpp Changed
31
 
1
@@ -222,9 +222,9 @@
2
         StRectI_t stRect(monInfo.rcMonitor.top, monInfo.rcMonitor.bottom, monInfo.rcMonitor.left, monInfo.rcMonitor.right);
3
         aMon.setVRect(stRect);
4
         aMon.setId(monCount);
5
-        aMon.setFreq((int )dm.dmDisplayFrequency);
6
+        aMon.setFreq((float )dm.dmDisplayFrequency);
7
         // TODO
8
-        aMon.setFreqMax((int )dm.dmDisplayFrequency);
9
+        aMon.setFreqMax((float )dm.dmDisplayFrequency);
10
 
11
         // ddMon.DeviceString = "Plug and Play monitor"
12
         // ddMon.DeviceName = "\\.\DISPLAY2\Monitor0"
13
@@ -424,7 +424,7 @@
14
                 break;
15
             }
16
             double aRate = std::floor(double(aMode.dotClock) / (double(aMode.hTotal) * double(aMode.vTotal)) + 0.5);
17
-            aMonitor.setFreq(int(aRate));
18
+            aMonitor.setFreq(float(aRate));
19
             break;
20
         }
21
 
22
@@ -461,7 +461,7 @@
23
                 aMaxRate = stMax(aMaxRate, aRate);
24
             }
25
         }
26
-        aMonitor.setFreqMax(int(aMaxRate));
27
+        aMonitor.setFreqMax(float(aMaxRate));
28
         XRRFreeOutputInfo(anOutputInfo);
29
 
30
         XRRFreeCrtcInfo(aCrtcInfo);
31
sview-17_04.tar.gz/StCore/StWinHandles.cpp -> sview-20_08.tar.gz/StCore/StWinHandles.cpp Changed
76
 
1
@@ -116,14 +116,21 @@
2
     #define ST_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR          0x00000001
3
     #define ST_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
4
 
5
+    // for EGL_KHR_context_flush_control
6
+    #define ST_EGL_CONTEXT_RELEASE_BEHAVIOR_KHR       0x2097
7
+    #define ST_EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR  0x0000
8
+    #define ST_EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
9
+
10
     const char* anEglExts = eglQueryString(myDisplay, EGL_EXTENSIONS);
11
     if(StGLContext::stglCheckExtension(anEglExts, "EGL_KHR_create_context")) {
12
+        const bool khrFlushControl = StGLContext::stglCheckExtension(anEglExts, "EGL_KHR_context_flush_control");
13
         const EGLint anEglCtxAttribs[] = {
14
             ST_EGL_CONTEXT_FLAGS_KHR, theDebugCtx ? ST_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0,
15
         #if defined(GL_ES_VERSION_2_0)
16
             EGL_CONTEXT_CLIENT_VERSION, 2,
17
         #endif
18
             //EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, ST_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
19
+            khrFlushControl ? ST_EGL_CONTEXT_RELEASE_BEHAVIOR_KHR : 0, khrFlushControl ? ST_EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR : 0,
20
             EGL_NONE
21
         };
22
 
23
@@ -240,6 +247,20 @@
24
 
25
 #else
26
 
27
+  // GLX_ARB_create_context
28
+#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
29
+    #define GLX_CONTEXT_DEBUG_BIT_ARB         0x00000001
30
+    #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
31
+    #define GLX_CONTEXT_MAJOR_VERSION_ARB     0x2091
32
+    #define GLX_CONTEXT_MINOR_VERSION_ARB     0x2092
33
+    #define GLX_CONTEXT_FLAGS_ARB             0x2094
34
+
35
+    // GLX_ARB_create_context_profile
36
+    #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB  0x00000001
37
+    #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
38
+    #define GLX_CONTEXT_PROFILE_MASK_ARB      0x9126
39
+#endif
40
+
41
 typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* , GLXFBConfig , GLXContext , Bool , const int* );
42
 
43
 StWinGlrc::StWinGlrc(StHandle<StXDisplay>& theDisplay,
44
@@ -248,13 +269,15 @@
45
   myRC(NULL) {
46
     const char* aGlxExts = glXQueryExtensionsString(theDisplay->hDisplay, DefaultScreen(theDisplay->hDisplay));
47
     if(StGLContext::stglCheckExtension(aGlxExts, "GLX_ARB_create_context_profile")) {
48
+        const bool khrFlushControl = StGLContext::stglCheckExtension(aGlxExts, "GLX_ARB_create_context_profile");
49
         glXCreateContextAttribsARB_t aCreateCtxFunc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
50
 
51
         int aCtxAttribs[] = {
52
             //GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
53
             //GLX_CONTEXT_MINOR_VERSION_ARB, 0,
54
-            GLX_CONTEXT_FLAGS_ARB,        theDebugCtx ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
55
             //GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
56
+            GLX_CONTEXT_FLAGS_ARB, theDebugCtx ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
57
+            khrFlushControl ? GLX_CONTEXT_RELEASE_BEHAVIOR_ARB : 0, khrFlushControl ? GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB : 0,
58
             None
59
         };
60
 
61
@@ -482,11 +505,12 @@
62
       if(aCtx.extAll->wglCreateContextAttribsARB != NULL) {
63
           // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
64
           // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB
65
-          int aCtxAttribs[] = {
66
+          const int aCtxAttribs[] = {
67
               //WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
68
               //WGL_CONTEXT_MINOR_VERSION_ARB, 2,
69
               //WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
70
-              WGL_CONTEXT_FLAGS_ARB,         theDebugCtx ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
71
+              WGL_CONTEXT_FLAGS_ARB, theDebugCtx ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
72
+              aCtx.khrFlushControl ? WGL_CONTEXT_RELEASE_BEHAVIOR_ARB : 0, aCtx.khrFlushControl ? WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB : 0,
73
               0, 0
74
           };
75
 
76
sview-17_04.tar.gz/StCore/StWinHandles.h -> sview-20_08.tar.gz/StCore/StWinHandles.h Changed
15
 
1
@@ -22,6 +22,13 @@
2
     #include "StCocoaView.h"
3
     #include "StCocoaWin.h"
4
 #elif defined(__linux__)
5
+    // exclude modern definitions and system-provided glext.h, should be defined before gl.h inclusion
6
+    #ifndef GL_GLEXT_LEGACY
7
+        #define GL_GLEXT_LEGACY
8
+    #endif
9
+    #ifndef GLX_GLXEXT_LEGACY
10
+        #define GLX_GLXEXT_LEGACY
11
+    #endif
12
     #include <GL/glx.h>
13
 #endif
14
 
15
sview-17_04.tar.gz/StCore/StWindow.cpp -> sview-20_08.tar.gz/StCore/StWindow.cpp Changed
28
 
1
@@ -136,6 +136,15 @@
2
     return myWin->isStereoOutput();
3
 }
4
 
5
+float StWindow::getMaximumTargetFps() const {
6
+    const StSearchMonitors& aMonitors = myWin->getMonitors();;
7
+    const StRectI_t aRect = myWin->getPlacement();
8
+    StMonitor aMon = aMonitors[aRect.center()];
9
+    return aMon.getFreq() >= 24
10
+         ? aMon.getFreq()
11
+         : 60; // fallback for unknown values
12
+}
13
+
14
 double StWindow::getTargetFps() const {
15
     return myTargetFps;
16
 }
17
@@ -433,6 +442,10 @@
18
     return StQuaternion<double>();
19
 }
20
 
21
+bool StWindow::getCustomProjection(StRectF_t& , StRectF_t& ) const {
22
+    return false;
23
+}
24
+
25
 bool StWindow::toSwapEyesHW() const {
26
     return myWin->myToSwapEyesHW;
27
 }
28
sview-17_04.tar.gz/StCore/StWindowImpl.cpp -> sview-20_08.tar.gz/StCore/StWindowImpl.cpp Changed
157
 
1
@@ -97,6 +97,10 @@
2
   myIsMouseMoved(false) {
3
     stMemZero(&attribs, sizeof(attribs));
4
     stMemZero(&signals, sizeof(signals));
5
+    myStEvent   .Type = stEvent_None;
6
+    myStEvent2  .Type = stEvent_None;
7
+    myStEventAux.Type = stEvent_None;
8
+    myScrollAcc.reset();
9
     attribs.IsNoDecor      = false;
10
     attribs.IsStereoOutput = false;
11
     attribs.IsGlStereo     = false;
12
@@ -123,6 +127,7 @@
13
     myTouches.Time = 0.0;
14
     myTouches.clearTouches();
15
 
16
+    myTap0Touch = StTouch::Empty();
17
     myTap1Touch.Type = stEvent_TouchCancel;
18
     myTap1Touch.Time = 0.0;
19
     myTap1Touch.clearTouches();
20
@@ -381,6 +386,9 @@
21
             case StWinAttr_ToAlignEven:
22
                 anIter[1] = (StWinAttr )attribs.ToAlignEven;
23
                 break;
24
+            case StWinAttr_ExclusiveFullScreen:
25
+                anIter[1] = (StWinAttr)attribs.IsExclusiveFullScr;
26
+                break;
27
             default:
28
                 ST_DEBUG_LOG("UNKNOWN window attribute #" + anIter[0] + " requested");
29
                 break;
30
@@ -492,6 +500,9 @@
31
             case StWinAttr_ToAlignEven:
32
                 attribs.ToAlignEven = (anIter[1] == 1);
33
                 break;
34
+            case StWinAttr_ExclusiveFullScreen:
35
+                attribs.IsExclusiveFullScr = (anIter[1] == 1);
36
+                break;
37
             default:
38
                 ST_DEBUG_LOG("UNKNOWN window attribute #" + anIter[0] + " requested");
39
                 break;
40
@@ -600,14 +611,19 @@
41
     }
42
 #elif defined(__ANDROID__)
43
     int aFlags = 0;
44
+    bool toWakeLock = false;
45
     if(attribs.ToBlockSleepDisplay) {
46
         aFlags |= AWINDOW_FLAG_KEEP_SCREEN_ON;
47
         myBlockSleep = BlockSleep_DISPLAY;
48
+    } else if(attribs.ToBlockSleepSystem) {
49
+        myBlockSleep = BlockSleep_SYSTEM;
50
+        toWakeLock = true;
51
     } else {
52
         myBlockSleep = BlockSleep_OFF;
53
     }
54
     if(myParentWin != NULL) {
55
         myParentWin->setWindowFlags(aFlags);
56
+        myParentWin->setWakeLock(myWindowTitle, toWakeLock);
57
     }
58
 #elif defined(__linux__)
59
     if(attribs.ToBlockSleepDisplay) { // || attribs.ToBlockSleepSystem
60
@@ -976,6 +992,14 @@
61
         CURSORINFO aCursor;
62
         aCursor.cbSize = sizeof(aCursor);
63
         if(GetCursorInfo(&aCursor) != FALSE) {
64
+            if (attribs.IsFullScreen
65
+            && !attribs.IsExclusiveFullScr
66
+            &&  myTiledCfg == TiledCfg_Separate
67
+            &&  myParentWin == NULL) {
68
+                // workaround for non-exclusive fullscreen mode
69
+                aCursor.ptScreenPos.y += 2;
70
+            }
71
+
72
             return StPointD_t((double(aCursor.ptScreenPos.x) - double(aWinRect.left())) / double(aWinRect.width()),
73
                               (double(aCursor.ptScreenPos.y) - double(aWinRect.top()))  / double(aWinRect.height()));
74
         }
75
@@ -1135,6 +1159,7 @@
76
             }
77
             if(myNbTouchesMax == 0) {
78
                 myTouches.Time = aTime;
79
+                myTap0Touch = theTouches.Touches[0];
80
             }
81
             myNbTouchesMax = stMax(myNbTouchesMax, theTouches.NbTouches);
82
 
83
@@ -1179,6 +1204,19 @@
84
                         myTap1Touch = aCopy;
85
                         myTap1Touch.Type = stEvent_TouchUp;
86
                         myTap1Touch.Time = aTime;
87
+                        StGLVec2 aDelta(myTap0Touch.PointX - aCopy.Touches[0].PointX,
88
+                                        myTap0Touch.PointY - aCopy.Touches[0].PointY);
89
+                        aDelta *= aScale;
90
+                        if(aDelta.modulus() <= THE_THRESHOLD_TAP.FromIdle) {
91
+                            myStEvent2.Type = stEvent_Gesture1Tap;
92
+                            myStEvent2.Gesture.clearGesture();
93
+                            myStEvent2.Gesture.Time = aTime;
94
+                            myStEvent2.Gesture.Point1X = aCopy.Touches[0].PointX;
95
+                            myStEvent2.Gesture.Point1Y = aCopy.Touches[0].PointY;
96
+                            signals.onGesture->emit(myStEvent2.Gesture);
97
+                        }
98
+                    }  else {
99
+                        myTap1Touch.Type = stEvent_TouchCancel;
100
                     }
101
                 } else {
102
                     myTap1Touch.Type = stEvent_TouchCancel;
103
@@ -1210,8 +1248,16 @@
104
     }
105
 
106
     bool toUpdate = false;
107
-    if(myTouches .NbTouches == 2
108
-    && theTouches.NbTouches == 2) {
109
+    if(myTouches .NbTouches == 1
110
+    && theTouches.NbTouches == 1) {
111
+        StTouch aTFrom = myTouches.Touches[0];
112
+        StTouch aTTo = theTouches.findTouchById(aTFrom.Id);
113
+        if(!aTTo.isDefined()) {
114
+            return;
115
+        }
116
+        myTouches.Touches[0] = aTTo;
117
+    } else if(myTouches .NbTouches == 2
118
+           && theTouches.NbTouches == 2) {
119
         StTouch aTFrom[2] = {
120
             myTouches.Touches[0],
121
             myTouches.Touches[1]
122
@@ -1422,9 +1468,33 @@
123
             case stEvent_MouseDown:
124
                 signals.onMouseDown->emit(anEvent.Button);
125
                 break;
126
-            case stEvent_MouseUp:
127
+            case stEvent_MouseUp: {
128
                 signals.onMouseUp->emit(anEvent.Button);
129
+                if(anEvent.Button.Button != ST_MOUSE_LEFT) {
130
+                    myDoubleClickTimer.stop();
131
+                    break;
132
+                }
133
+
134
+                // check double click
135
+                const StRectI_t& aWinRect = attribs.IsFullScreen ? myRectFull : myRectNorm;
136
+                const StPointD_t aNewPnt(anEvent.Button.PointX, anEvent.Button.PointY);
137
+                const StPointD_t aDeltaPx = (myDoubleClickPnt - aNewPnt) * StPointD_t(aWinRect.width(), aWinRect.height());
138
+                if(myDoubleClickTimer.isOn()
139
+                && myDoubleClickTimer.getElapsedTime() < 0.4
140
+                && aDeltaPx.cwiseAbs().maxComp() < 3) {
141
+                    myStEvent2.Type = stEvent_Gesture1DoubleTap;
142
+                    myStEvent2.Gesture.clearGesture();
143
+                    myStEvent2.Gesture.Time = anEvent.Button.Time;
144
+                    myStEvent2.Gesture.Point1X = (float )anEvent.Button.PointX;
145
+                    myStEvent2.Gesture.Point1Y = (float )anEvent.Button.PointY;
146
+                    myDoubleClickTimer.stop();
147
+                    signals.onGesture->emit(myStEvent2.Gesture);
148
+                } else {
149
+                    myDoubleClickTimer.restart();
150
+                }
151
+                myDoubleClickPnt = aNewPnt;
152
                 break;
153
+            }
154
             case stEvent_TouchDown:
155
             case stEvent_TouchUp:
156
             case stEvent_TouchMove:
157
sview-17_04.tar.gz/StCore/StWindowImpl.h -> sview-20_08.tar.gz/StCore/StWindowImpl.h Changed
30
 
1
@@ -99,8 +99,10 @@
2
     ST_LOCAL bool wndCreateWindows(); // called from non-main thread
3
     ST_LOCAL LRESULT stWndProc(HWND , UINT , WPARAM , LPARAM );
4
 #elif defined(__APPLE__)
5
+    ST_DISABLE_DEPRECATION_WARNINGS
6
     ST_LOCAL void doCreateWindows(NSOpenGLContext* theGLContextMaster,
7
                                   NSOpenGLContext* theGLContextSlave);
8
+    ST_ENABLE_DEPRECATION_WARNINGS
9
 #endif
10
 
11
         public:
12
@@ -286,6 +288,7 @@
13
     bool               myIsPreciseCursor; //!< flag indicating that last mouse cursor position was updated by precise input device
14
     StTouchEvent       myTouches;         //!< current state of touch screen
15
     StTouchEvent       myTap1Touch;       //!< previous tap touch
16
+    StTouch            myTap0Touch;       //!< started tap
17
     int                myNbTouchesMax;    //!< maximum touches within current sequence
18
     StRectI_t          myRectNorm;        //!< master window coordinates in normal     state
19
     StRectI_t          myRectFull;        //!< master window coordinates in fullscreen state
20
@@ -477,6 +480,9 @@
21
     StEvent        myStEvent;          //!< temporary event object (to be used in message loop thread)
22
     StEvent        myStEvent2;         //!< temporary event object (to be used in message loop thread)
23
     StEvent        myStEventAux;       //!< extra temporary event object (to be used in StWindow creation thread)
24
+    StScrollEvent  myScrollAcc;        //!< extra temporary event object accumulating mouse scroll events
25
+    StTimer        myDoubleClickTimer; //!< timer for detecting double click
26
+    StPointD_t     myDoubleClickPnt;   //!< double click point
27
     int            myAlignDL;          //!< extra window shift applied for alignment (left)
28
     int            myAlignDR;          //!< extra window shift applied for alignment (right)
29
     int            myAlignDT;          //!< extra window shift applied for alignment (top)
30
sview-17_04.tar.gz/StCore/StWindowImplAnd.cpp -> sview-20_08.tar.gz/StCore/StWindowImplAnd.cpp Changed
99
 
1
@@ -78,7 +78,7 @@
2
  * Update StWindow position according to native parent position.
3
  */
4
 void StWindowImpl::updateChildRect() {
5
-    if(!attribs.IsFullScreen && (ANativeWindow* )myParentWin != NULL) {
6
+    if(!attribs.IsFullScreen && myParentWin != NULL) {
7
         //myRectNorm.right()  = myRectNorm.left() + widthReturn;
8
         //myRectNorm.bottom() = myRectNorm.top() + heightReturn;
9
 
10
@@ -169,8 +169,9 @@
11
             const float      aWinSizeY = aWinRect.height();
12
 
13
             // at least single point is defined
14
-            StPointD_t aPos0(double(AMotionEvent_getX(theEvent, 0)) / double(aWinSizeX),
15
-                             double(AMotionEvent_getY(theEvent, 0)) / double(aWinSizeY));
16
+            StPointD_t aPos0Px(AMotionEvent_getX(theEvent, 0), AMotionEvent_getY(theEvent, 0));
17
+            StPointD_t aPos0(double(aPos0Px.x()) / double(aWinSizeX),
18
+                             double(aPos0Px.y()) / double(aWinSizeY));
19
 
20
             myStEvent.Type      = stEvent_None;
21
             myStEvent.Base.Time = getEventTime(); /// int64_t AMotionEvent_getEventTime(theEvent);
22
@@ -283,6 +284,23 @@
23
             } else if(anAction == AMOTION_EVENT_ACTION_UP) {
24
                 myStEvent.Type = stEvent_MouseUp;
25
                 signals.onMouseUp->emit(myStEvent.Button);
26
+            } else if(anAction == AMOTION_EVENT_ACTION_SCROLL) {
27
+                float aScrollX = AMotionEvent_getAxisValue(theEvent, AMOTION_EVENT_AXIS_HSCROLL, 0);
28
+                float aScrollY = AMotionEvent_getAxisValue(theEvent, AMOTION_EVENT_AXIS_VSCROLL, 0);
29
+                myStEvent.Type = stEvent_Scroll;
30
+                myStEvent.Scroll.init(myStEvent.Base.Time, myMousePt.x(), myMousePt.y(),
31
+                                      aScrollX, aScrollY, false);
32
+                if((myStEvent.Scroll.Time - myScrollAcc.Time) > 0.1
33
+                 || std::abs(aPos0Px.x() - myScrollAcc.PointX) > 10
34
+                 || std::abs(aPos0Px.y() - myScrollAcc.PointY) > 10) {
35
+                    myScrollAcc.reset();
36
+                }
37
+                myScrollAcc.Time = myStEvent.Scroll.Time;
38
+                myScrollAcc.PointX = aPos0Px.x();
39
+                myScrollAcc.PointY = aPos0Px.y();
40
+                myStEvent.Scroll.StepsX = myScrollAcc.accumulateStepsX(int(aScrollX * 1000.0), 1000);
41
+                myStEvent.Scroll.StepsY = myScrollAcc.accumulateStepsY(int(aScrollY * 1000.0), 1000);
42
+                signals.onScroll->emit(myStEvent.Scroll);
43
             }
44
             return;
45
         }
46
@@ -475,18 +493,34 @@
47
 
48
     // check onNewIntent event
49
     StString aDndFile;
50
+    myParentWin->setWindowTitle(myWindowTitle);
51
     myParentWin->setHardwareStereoOn(myToEnableStereoHW);
52
     myParentWin->setTrackOrientation(myToTrackOrient);
53
     myParentWin->setHideSystemBars(myToHideStatusBar, myToHideNavBar);
54
-    myParentWin->fetchState(aDndFile, myQuaternion, myToSwapEyesHW);
55
+    myParentWin->fetchState(aDndFile, myQuaternion, myToSwapEyesHW, myKeysState);
56
     if(!aDndFile.isEmpty()) {
57
-        std::vector<const char*> aDndList;
58
-        aDndList.push_back(aDndFile.toCString());
59
-        myStEvent.Type = stEvent_FileDrop;
60
-        myStEvent.DNDrop.Time = getEventTime();
61
-        myStEvent.DNDrop.NbFiles = aDndList.size();
62
-        myStEvent.DNDrop.Files   = &aDndList[0];
63
-        myEventsBuffer.append(myStEvent);
64
+        // notice - unpress event will NOT be generated!
65
+        myStEvent.Type      = stEvent_KeyDown;
66
+        myStEvent.Key.Time  = getEventTime();
67
+        myStEvent.Key.Flags = ST_VF_NONE;
68
+        if(aDndFile == "ACTION_PLAY_PREV") {
69
+            myStEvent.Key.VKey  = ST_VK_MEDIA_PREV_TRACK;
70
+            myEventsBuffer.append(myStEvent);
71
+        } else if(aDndFile == "ACTION_PLAY_NEXT") {
72
+            myStEvent.Key.VKey  = ST_VK_MEDIA_NEXT_TRACK;
73
+            myEventsBuffer.append(myStEvent);
74
+        } else if(aDndFile == "ACTION_PLAY_PAUSE") {
75
+            myStEvent.Key.VKey  = ST_VK_MEDIA_PLAY_PAUSE;
76
+            myEventsBuffer.append(myStEvent);
77
+        } else {
78
+            std::vector<const char*> aDndList;
79
+            aDndList.push_back(aDndFile.toCString());
80
+            myStEvent.Type = stEvent_FileDrop;
81
+            myStEvent.DNDrop.Time = getEventTime();
82
+            myStEvent.DNDrop.NbFiles = aDndList.size();
83
+            myStEvent.DNDrop.Files   = &aDndList[0];
84
+            myEventsBuffer.append(myStEvent);
85
+        }
86
     }
87
 
88
     updateActiveState();
89
@@ -519,7 +553,8 @@
90
     }
91
 
92
     myIsMouseMoved = false;
93
-    if(myMousePt.x() >= 0.0 && myMousePt.x() <= 1.0 && myMousePt.y() >= 0.0 && myMousePt.y() <= 1.0) {
94
+    if(myIsPreciseCursor
95
+    && myMousePt.x() >= 0.0 && myMousePt.x() <= 1.0 && myMousePt.y() >= 0.0 && myMousePt.y() <= 1.0) {
96
         StPointD_t aDspl = myMousePt - anOldMousePt;
97
         if(std::abs(aDspl.x()) >= 0.0008 || std::abs(aDspl.y()) >= 0.0008) {
98
             myIsMouseMoved = true;
99
sview-17_04.tar.gz/StCore/StWindowImplLin.cpp -> sview-20_08.tar.gz/StCore/StWindowImplLin.cpp Changed
10
 
1
@@ -962,7 +962,7 @@
2
                     myStEvent.Scroll.StepsX = 0;
3
                     myStEvent.Scroll.StepsY = aBtnEvent->button == 4 ? 1 : -1;
4
                     myStEvent.Scroll.DeltaX = 0.0;
5
-                    myStEvent.Scroll.DeltaY = 10.0f * myStEvent.Scroll.StepsY;
6
+                    myStEvent.Scroll.DeltaY = myStEvent.Scroll.StepsY;
7
                     myStEvent.Scroll.IsFromMultiTouch = false;
8
                     signals.onScroll->emit(myStEvent.Scroll);
9
                     break;
10
sview-17_04.tar.gz/StCore/StWindowImplMac.mm -> sview-20_08.tar.gz/StCore/StWindowImplMac.mm Changed
11
 
1
@@ -274,7 +274,9 @@
2
     StCocoaLocalPool aLocalPool;
3
 
4
     const bool isNoAccel = false;
5
+ST_DISABLE_DEPRECATION_WARNINGS
6
     const NSOpenGLPixelFormatAttribute aDummyAttrib = NSOpenGLPFACompliant;
7
+ST_ENABLE_DEPRECATION_WARNINGS
8
     NSOpenGLPixelFormatAttribute anAttribs[] = {
9
         attribs.IsGlStereo ? NSOpenGLPFAStereo : aDummyAttrib,
10
         //NSOpenGLPFAColorSize,   32,
11
sview-17_04.tar.gz/StCore/StWindowImplWin.cpp -> sview-20_08.tar.gz/StCore/StWindowImplWin.cpp Changed
71
 
1
@@ -875,25 +875,32 @@
2
             return 0;
3
         }
4
         case WM_MOUSEWHEEL:    // vertical wheel
5
-        //case WM_MOUSEHWHEEL:   // horizontal wheel (only Vista+)
6
+        case WM_MOUSEHWHEEL:   // horizontal wheel (only Vista+)
7
         {
8
             const StRectI_t aWinRect = getPlacement();
9
             int aMouseXPx = int(short(LOWORD(lParam))) - aWinRect.left();
10
             int aMouseYPx = int(short(HIWORD(lParam))) - aWinRect.top();
11
 
12
-            int aZDelta = GET_WHEEL_DELTA_WPARAM(wParam); // / WHEEL_DELTA;
13
-            //if(GET_X_LPARAM(lParam) != 0)
14
-
15
-            myStEvent.Type = stEvent_Scroll;
16
-            myStEvent.Scroll.Time   = getEventTime(myEvent.time);
17
-            myStEvent.Scroll.PointX = double(aMouseXPx) / double(aWinRect.width());
18
-            myStEvent.Scroll.PointY = double(aMouseYPx) / double(aWinRect.height());
19
-            myStEvent.Scroll.StepsX = 0;
20
-            myStEvent.Scroll.StepsY = (aZDelta > 0) ? 1 : -1;
21
-            myStEvent.Scroll.DeltaX = 0.0;
22
-            myStEvent.Scroll.DeltaY = 10.0f * myStEvent.Scroll.StepsY;
23
-            myStEvent.Scroll.IsFromMultiTouch = false;
24
-
25
+            const bool  isVert   = (uMsg == WM_MOUSEWHEEL);
26
+            const int   aZDelta  = GET_WHEEL_DELTA_WPARAM(wParam);
27
+            const float aDeltaSt = float(aZDelta) / float(WHEEL_DELTA);
28
+
29
+            myStEvent.Scroll.init(getEventTime(myEvent.time),
30
+                                  double(aMouseXPx) / double(aWinRect.width()),
31
+                                  double(aMouseYPx) / double(aWinRect.height()),
32
+                                  !isVert ? aDeltaSt : 0.0f,
33
+                                   isVert ? aDeltaSt : 0.0f,
34
+                                  false);
35
+            if((myStEvent.Scroll.Time - myScrollAcc.Time) > 0.1
36
+             || std::abs(aMouseXPx - (int)myScrollAcc.PointX) > 10
37
+             || std::abs(aMouseYPx - (int)myScrollAcc.PointY) > 10) {
38
+                myScrollAcc.reset();
39
+            }
40
+            myScrollAcc.Time = myStEvent.Scroll.Time;
41
+            myScrollAcc.PointX = aMouseXPx;
42
+            myScrollAcc.PointY = aMouseYPx;
43
+            myStEvent.Scroll.StepsX = myScrollAcc.accumulateStepsX(!isVert ? aZDelta : 0, WHEEL_DELTA);
44
+            myStEvent.Scroll.StepsY = myScrollAcc.accumulateStepsY( isVert ? aZDelta : 0, WHEEL_DELTA);
45
             myEventsBuffer.append(myStEvent);
46
             return 0;
47
         }
48
@@ -1139,10 +1146,19 @@
49
         } else {
50
             // resize Master GL-subwindow
51
             myTiledCfg = TiledCfg_Separate;
52
-            const GLsizei aSizeX = (attribs.IsFullScreen) ? myRectFull.width()  : myRectNorm.width();
53
-            const GLsizei aSizeY = (attribs.IsFullScreen) ? myRectFull.height() : myRectNorm.height();
54
+            int aTop   = 0;
55
+            int aSizeX = (attribs.IsFullScreen) ? myRectFull.width()  : myRectNorm.width();
56
+            int aSizeY = (attribs.IsFullScreen) ? myRectFull.height() : myRectNorm.height();
57
+            if (attribs.IsFullScreen
58
+            && !attribs.IsExclusiveFullScr)
59
+            {
60
+              // workaround slow switching into fullscreen mode and back on Windows 10
61
+              // due to OpenGL driver implicitly activating an exclusive GPU usage mode
62
+              aTop   -= 2;
63
+              aSizeY += 2;
64
+            }
65
             SetWindowPos(myMaster.hWindowGl, HWND_TOP,
66
-                         0, 0, aSizeX, aSizeY,
67
+                         0, aTop, aSizeX, aSizeY,
68
                          SWP_NOACTIVATE);
69
         }
70
     }
71
sview-17_04.tar.gz/StCore/StXDisplay.h -> sview-20_08.tar.gz/StCore/StXDisplay.h Changed
16
 
1
@@ -16,6 +16,14 @@
2
 #include <X11/Xlib.h>
3
 #include <X11/Xatom.h>
4
 #include <X11/Xutil.h>
5
+
6
+// exclude modern definitions and system-provided glext.h, should be defined before gl.h inclusion
7
+#ifndef GL_GLEXT_LEGACY
8
+    #define GL_GLEXT_LEGACY
9
+#endif
10
+#ifndef GLX_GLXEXT_LEGACY
11
+    #define GLX_GLXEXT_LEGACY
12
+#endif
13
 #include <GL/glx.h>
14
 
15
 #include <StStrings/StString.h>
16
sview-17_04.tar.gz/StCore/stvkeysxarray.h -> sview-20_08.tar.gz/StCore/stvkeysxarray.h Changed
19
 
1
@@ -37,7 +37,7 @@
2
     ST_VK_COMMA,     // 0x2C = XK_comma
3
     ST_VK_OEM_MINUS, // 0x2D = XK_minus
4
     ST_VK_PERIOD,    // 0x2E = XK_period
5
-    0, // 0x2F
6
+    ST_VK_SLASH,  // 0x2F = XK_slash
7
     ST_VK_0,      // 0x30 = XK_0
8
     ST_VK_1,      // 0x31 = XK_1
9
     ST_VK_2,      // 0x32 = XK_2
10
@@ -86,7 +86,7 @@
11
     ST_VK_BRACKETRIGHT, // 0x5D = XK_bracketright
12
     ST_VK_NULL,   // 0x5E
13
     ST_VK_NULL,   // 0x5F
14
-    ST_VK_NULL,   // 0x60
15
+    ST_VK_TILDE,  // 0x60 = XK_grave
16
     ST_VK_A,      // 0x61 = XK_a
17
     ST_VK_B,      // 0x62 = XK_b
18
     ST_VK_C,      // 0x63 = XK_c
19
sview-17_04.tar.gz/StDiagnostics/StDiagnostics.cpp -> sview-20_08.tar.gz/StDiagnostics/StDiagnostics.cpp Changed
28
 
1
@@ -97,6 +97,13 @@
2
         myGUI.nullify();
3
         return false;
4
     }
5
+
6
+    StRectF_t aFrustL, aFrustR;
7
+    if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
8
+        myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
9
+    } else {
10
+        myGUI->changeCamera()->resetCustomProjection();
11
+    }
12
     myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
13
 
14
     registerHotKeys();
15
@@ -108,6 +115,12 @@
16
         return;
17
     }
18
 
19
+    StRectF_t aFrustL, aFrustR;
20
+    if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
21
+        myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
22
+    } else {
23
+        myGUI->changeCamera()->resetCustomProjection();
24
+    }
25
     myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
26
 }
27
 
28
sview-17_04.tar.gz/StDiagnostics/StDiagnostics.rc -> sview-20_08.tar.gz/StDiagnostics/StDiagnostics.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereoscopic Device Diagnostics\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2010-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2010-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StDiagnostics\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StDiagnostics/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StDiagnostics/lang/spanish/StDiagnostics.lng Added
5
 
1
@@ -0,0 +1,3 @@
2
+# Spanish translation file for StDiagnostics plugin
3
+# @author Kirill Gavrilov
4
+--------
5
sview-17_04.tar.gz/StGLWidgets/StGLCombobox.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLCombobox.cpp Changed
58
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2015 Kirill Gavrilov <kirill@sview.ru
5
+ * Copyright © 2015-2020 Kirill Gavrilov <kirill@sview.ru
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -11,6 +11,7 @@
10
 
11
 #include <StGLWidgets/StGLMenuItem.h>
12
 #include <StGLWidgets/StGLMessageBox.h>
13
+#include <StGLWidgets/StGLScrollArea.h>
14
 #include <StGLWidgets/StGLRootWidget.h>
15
 
16
 /**
17
@@ -27,7 +28,7 @@
18
         const int aHeight = myRoot->getRootFullSizeY();
19
         changeRectPx().right()  = aWidth;
20
         changeRectPx().bottom() = aHeight;
21
-        create(StString(), StString(), aWidth, aHeight);
22
+        create(StString(), StString(), aWidth, aHeight, false);
23
     }
24
 
25
 };
26
@@ -59,7 +60,7 @@
27
     StGLWidget*     aMenuParent = aRoot;
28
     if(aRoot->isMobile()) {
29
         myBack = new StGLContextBackground(aRoot);
30
-        aMenuParent = myBack;
31
+        aMenuParent = myBack->getContent();
32
     }
33
 
34
     int aLeft = 0;
35
@@ -78,14 +79,18 @@
36
 }
37
 
38
 void StGLCombobox::ListBuilder::display() {
39
+    StGLRootWidget* aRoot = myMenu->getRoot();
40
+    const int aRootX = aRoot->getRectPx().width();
41
+    const int aRootY = aRoot->getRectPx().height();
42
     if(myBack != NULL) {
43
         myBack->stglInit();
44
+        if(myBack->getContent()->isScrollable()) {
45
+            myMenu->setCorner(StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
46
+            myMenu->stglResize();
47
+        }
48
     } else {
49
-        StGLRootWidget* aRoot = myMenu->getRoot();
50
         myMenu->stglUpdateSubmenuLayout();
51
-        StRectI_t aRect  = myMenu->getRectPxAbsolute();
52
-        const int aRootX = aRoot->getRectPx().width();
53
-        const int aRootY = aRoot->getRectPx().height();
54
+        StRectI_t aRect = myMenu->getRectPxAbsolute();
55
         if(aRect.width()  >= aRootX) {
56
             myMenu->changeRectPx().moveLeftTo(0);
57
         } else if(aRect.right() > aRoot->getRectPx().right()) {
58
sview-17_04.tar.gz/StGLWidgets/StGLImageProgram.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLImageProgram.cpp Changed
541
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -14,26 +14,66 @@
10
 #include <StFile/StRawFile.h>
11
 
12
 namespace {
13
-    const char F_DEF_2D[] =
14
+    const char F_DEF_2D_ALPHA[] =
15
         "#define stSampler sampler2D\n"
16
-        "#define stTexture(theSampler, theCoords) texture2D(theSampler, theCoords.xy)\n";
17
-    const char F_DEF_CUBEMAP[] =
18
+        "#define stTexture(theSampler, theCoords) texture2D(theSampler, theCoords.xy)\n"
19
+        "#define stAlpha a\n";
20
+    const char F_DEF_2D_RED[] =
21
+        "#define stSampler sampler2D\n"
22
+        "#define stTexture(theSampler, theCoords) texture2D(theSampler, theCoords.xy)\n"
23
+        "#define stAlpha r\n";
24
+    const char F_DEF_CUBEMAP_ALPHA[] =
25
+        "#define stSampler samplerCube\n"
26
+        "#define stTexture(theSampler, theCoords) textureCube(theSampler, theCoords)\n"
27
+        "#define stAlpha a\n";
28
+    const char F_DEF_CUBEMAP_RED[] =
29
         "#define stSampler samplerCube\n"
30
-        "#define stTexture(theSampler, theCoords) textureCube(theSampler, theCoords)\n";
31
+        "#define stTexture(theSampler, theCoords) textureCube(theSampler, theCoords)\n"
32
+        "#define stAlpha r\n";
33
 }
34
 
35
-void StGLImageProgram::regToRgb(const int       thePartIndex,
36
+void StGLImageProgram::regToRgb(const StGLContext& theCtx,
37
+                                const int       thePartIndex,
38
                                 const StString& theText) {
39
   registerFragmentShaderPart(FragSection_ToRgb, thePartIndex,
40
-                             StString(F_DEF_2D)      + theText);
41
+                             StString(theCtx.arbTexRG ? F_DEF_2D_RED : F_DEF_2D_ALPHA) + theText);
42
   registerFragmentShaderPart(FragSection_ToRgb, FragToRgb_CUBEMAP + thePartIndex,
43
-                             StString(F_DEF_CUBEMAP) + theText);
44
+                             StString(theCtx.arbTexRG ? F_DEF_CUBEMAP_RED : F_DEF_CUBEMAP_ALPHA) + theText);
45
 }
46
 
47
 StGLImageProgram::StGLImageProgram()
48
-: myColorScale(1.0f, 1.0f, 1.0f) {
49
+: myColorScale(1.0f, 1.0f, 1.0f),
50
+  myIsRegistered(false) {
51
     myTitle = "StGLImageProgram";
52
 
53
+    params.gamma = new StFloat32Param(1.0f);
54
+    params.gamma->setMinMaxValues(0.05f, 99.0f);
55
+    params.gamma->setEffectiveMinMaxValues(0.05f, 2.0f);
56
+    params.gamma->setDefValue(1.0f);
57
+    params.gamma->setStep(0.05f);
58
+    params.gamma->setTolerance(0.0001f);
59
+
60
+    params.brightness = new StFloat32Param(1.0f);
61
+    params.brightness->setMinMaxValues(0.0f, 99.0f);
62
+    params.brightness->setDefValue(1.0f);
63
+    params.brightness->setEffectiveMinMaxValues(0.0f, 5.0f);
64
+    params.brightness->setStep(0.05f);
65
+    params.brightness->setTolerance(0.0001f);
66
+
67
+    params.saturation = new StFloat32Param(1.0f);
68
+    params.saturation->setMinMaxValues(-10.0f, 99.0f);
69
+    params.saturation->setEffectiveMinMaxValues(0.0f, 2.0f);
70
+    params.saturation->setDefValue(1.0f);
71
+    params.saturation->setStep(0.05f);
72
+    params.saturation->setTolerance(0.0001f);
73
+}
74
+
75
+void StGLImageProgram::registerFragments(const StGLContext& theCtx) {
76
+    if(myIsRegistered) {
77
+        return;
78
+    }
79
+    myIsRegistered = true;
80
+
81
     const char F_SHADER_GET_COLOR_BLEND[] =
82
        "uniform sampler2D uTexture;\n"
83
        "uniform vec4 uTexData;\n"
84
@@ -79,26 +119,71 @@
85
         "    color = pow(color, uGamma);\n"
86
         "}\n\n");
87
 
88
+    // equiangular cubemap texture coordinates correction
89
+    registerFragmentShaderPart(FragSection_GetTexCoords, FragTexEAC_Off,
90
+                               "vec3 getTexCoords(in vec3 theCoords, in vec4 theClamp) { return theCoords; }\n\n");
91
+    registerFragmentShaderPart(FragSection_GetTexCoords, FragTexEAC_On,
92
+                               "#define ST_PI 3.1415926535897932384626433832795\n"
93
+                               "vec3 getTexCoords(in vec3 theCoords, in vec4 theClamp) {\n"
94
+                               "    vec3 aCoords = theCoords;\n"
95
+                               "    aCoords.x = 4.0 / ST_PI * atan(theCoords.x);\n"
96
+                               "    aCoords.y = 4.0 / ST_PI * atan(theCoords.y);\n"
97
+                               "    aCoords.z = 4.0 / ST_PI * atan(theCoords.z);\n"
98
+                               "\n"
99
+                               "    float aClampX = abs(theClamp.x) < 1.0 ? theClamp.w * 2.0 : 0.0;\n"
100
+                               "    if(theClamp.x >= 0.0) {\n"
101
+                               "        aCoords.x = -1.0 + theClamp.x * (aCoords.x + 1.0);\n"
102
+                               "        aCoords.x = clamp(aCoords.x, -1.0 + aClampX, 1.0 * theClamp.x);\n"
103
+                               "    } else {\n"
104
+                               "        aCoords.x =  1.0 + theClamp.x * (1.0 - aCoords.x);\n"
105
+                               "        aCoords.x = clamp(aCoords.x, 1.0 * theClamp.x, 1.0 - aClampX);\n"
106
+                               "    }\n"
107
+                               "\n"
108
+                               "    float aClampY = abs(theClamp.y) < 1.0 ? theClamp.w * 2.0 : 0.0;\n"
109
+                               "    if(theClamp.y >= 0.0) {\n"
110
+                               "        aCoords.y = -1.0 + theClamp.y * (aCoords.y + 1.0);\n"
111
+                               "        aCoords.y = clamp(aCoords.y, -1.0 + aClampY, 1.0 * theClamp.y);\n"
112
+                               "    } else {\n"
113
+                               "        aCoords.y =  1.0 + theClamp.y * (1.0 - aCoords.y);\n"
114
+                               "        aCoords.y = clamp(aCoords.y, 1.0 * theClamp.y, 1.0 - aClampY);\n"
115
+                               "    }\n"
116
+                               "\n"
117
+                               "    float aClampZ = abs(theClamp.z) < 1.0 ? theClamp.w * 2.0 : 0.0;\n"
118
+                               "    if(theClamp.z >= 0.0) {\n"
119
+                               "        aCoords.z = -1.0 + theClamp.z * (aCoords.z + 1.0);\n"
120
+                               "        aCoords.z = clamp(aCoords.z, -1.0 + aClampZ, 1.0 * theClamp.z);\n"
121
+                               "    } else {\n"
122
+                               "        aCoords.z =  1.0 + theClamp.z * (1.0 - aCoords.z);\n"
123
+                               "        aCoords.z = clamp(aCoords.z, 1.0 * theClamp.z, 1.0 - aClampZ);\n"
124
+                               "    }\n"
125
+                               "    return aCoords;\n"
126
+                               "}\n\n");
127
+
128
     registerFragmentShaderPart(FragSection_ToRgb, FragToRgb_FromRgb,
129
-        "void convertToRGB(inout vec4 color, in vec3 texCoord) {}\n\n");
130
-
131
-    registerFragmentShaderPart(FragSection_ToRgb, FragToRgb_FromRgba,
132
-        "void convertToRGB(inout vec4 color, in vec3 texCoord) {\n"
133
-        "    vec4 backColor;\n"
134
-        "    bool evenX = int(mod(floor(gl_FragCoord.x + 1.5), 16.0)) >= 8;\n" // just simple 8 pixels check-board
135
-        "    bool evenY = int(mod(floor(gl_FragCoord.y + 1.5), 16.0)) >= 8;\n"
136
-        "    if((evenX && evenY) || (!evenX && !evenY)) {\n"
137
-        "        backColor = vec4(0.4, 0.4, 0.4, 1.0);\n"
138
-        "    } else {\n"
139
-        "        backColor = vec4(0.6, 0.6, 0.6, 1.0);\n"
140
-        "    }\n"
141
-        "    color = mix(backColor, color, color.a);\n"
142
+        "void convertToRGB(inout vec4 color, in vec3 texCoord, in vec3 texCoordA) {}\n\n");
143
+
144
+    const char F_ALPHA_BACKGROUND[] =
145
+        "void drawAlphaBackground(inout vec4 theColor) {\n"
146
+        "    bool anEvenX = int(mod(floor(gl_FragCoord.x + 1.5), 16.0)) >= 8;\n" // just simple 8 pixels check-board
147
+        "    bool anEvenY = int(mod(floor(gl_FragCoord.y + 1.5), 16.0)) >= 8;\n"
148
+        "    vec4 aBackColor = vec4(0.6, 0.6, 0.6, 1.0);\n"
149
+        "    if((anEvenX && anEvenY) || (!anEvenX && !anEvenY)) {\n"
150
+        "        aBackColor = vec4(0.4, 0.4, 0.4, 1.0);\n"
151
+        "    };\n"
152
+        "    theColor = mix(aBackColor, theColor, theColor.a);\n"
153
+        "}\n\n";
154
+
155
+    registerFragmentShaderPart(FragSection_ToRgb, FragToRgb_FromRgba, StString()
156
+      + F_ALPHA_BACKGROUND
157
+      + "void convertToRGB(inout vec4 color, in vec3 texCoord, in vec3 texCoordA) {\n"
158
+        "    drawAlphaBackground(color);\n"
159
         "}\n\n");
160
-    registerFragmentShaderPart(FragSection_ToRgb, FragToRgb_FromGray,
161
-        "void convertToRGB(inout vec4 color, in vec3 texCoord) {\n"
162
-        "    color.r = color.a;\n" // gray scale stored in alpha
163
-        "    color.g = color.a;\n"
164
-        "    color.b = color.a;\n"
165
+
166
+    regToRgb(theCtx, FragToRgb_FromGray,
167
+        "void convertToRGB(inout vec4 color, in vec3 texCoord, in vec3 texCoordA) {\n"
168
+        "    color.r = color.stAlpha;\n" // gray scale stored in alpha
169
+        "    color.g = color.stAlpha;\n"
170
+        "    color.b = color.stAlpha;\n"
171
         "}\n\n");
172
 
173
     // color conversion shaders
174
@@ -110,7 +195,7 @@
175
        "                                        0.0,        0.0,        0.0, 1.0);"
176
        "const vec4 THE_GAMMA_XYZ =       vec4(2.6, 2.6, 2.6, 1.0);"
177
        "const vec4 THE_GAMMA_RGB = 1.0 / vec4(2.2, 2.2, 2.2, 1.0);"
178
-       "void convertToRGB(inout vec4 theColor, in vec3 texCoord) {\n"
179
+       "void convertToRGB(inout vec4 theColor, in vec3 texCoord, in vec3 texCoordA) {\n"
180
        "    vec4 aColor = pow(theColor, THE_GAMMA_XYZ);"
181
        "    aColor = THE_XYZ2RGB_MAT * aColor;\n"
182
        "    aColor = pow(aColor, THE_GAMMA_RGB);"
183
@@ -120,8 +205,23 @@
184
     const char F_SHADER_YUV2RGB_MPEG[] =
185
        "uniform stSampler uTextureU;\n"
186
        "uniform stSampler uTextureV;\n"
187
-       "void convertToRGB(inout vec4 color, in vec3 texCoordUV) {\n"
188
-       "    vec3 colorYUV = vec3(color.a, stTexture(uTextureU, texCoordUV).a, stTexture(uTextureV, texCoordUV).a);\n"
189
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
190
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).stAlpha, stTexture(uTextureV, texCoordUV).stAlpha);\n"
191
+       "    colorYUV   *= TheRangeBits;\n"
192
+       "    colorYUV.x  = 1.1643 * (colorYUV.x - 0.0625);\n"
193
+       "    colorYUV.y -= 0.5;\n"
194
+       "    colorYUV.z -= 0.5;\n"
195
+       "    color.r = colorYUV.x +  1.5958 * colorYUV.z;\n"
196
+       "    color.g = colorYUV.x - 0.39173 * colorYUV.y - 0.81290 * colorYUV.z;\n"
197
+       "    color.b = colorYUV.x +   2.017 * colorYUV.y;\n"
198
+       "}\n\n";
199
+
200
+    const char F_SHADER_YUVA2RGB_MPEG[] =
201
+       "uniform stSampler uTextureU;\n"
202
+       "uniform stSampler uTextureV;\n"
203
+       "uniform stSampler uTextureA;\n"
204
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
205
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).stAlpha, stTexture(uTextureV, texCoordUV).stAlpha);\n"
206
        "    colorYUV   *= TheRangeBits;\n"
207
        "    colorYUV.x  = 1.1643 * (colorYUV.x - 0.0625);\n"
208
        "    colorYUV.y -= 0.5;\n"
209
@@ -129,13 +229,15 @@
210
        "    color.r = colorYUV.x +  1.5958 * colorYUV.z;\n"
211
        "    color.g = colorYUV.x - 0.39173 * colorYUV.y - 0.81290 * colorYUV.z;\n"
212
        "    color.b = colorYUV.x +   2.017 * colorYUV.y;\n"
213
+       "    color.a = stTexture(uTextureA, texCoordA).stAlpha;\n" // TODO how to handle TheRangeBits?
214
+       "    drawAlphaBackground(color);\n"
215
        "}\n\n";
216
 
217
     const char F_SHADER_YUV2RGB_FULL[] =
218
        "uniform stSampler uTextureU;\n"
219
        "uniform stSampler uTextureV;\n"
220
-       "void convertToRGB(inout vec4 color, in vec3 texCoordUV) {\n"
221
-       "    vec3 colorYUV = vec3(color.a, stTexture(uTextureU, texCoordUV).a, stTexture(uTextureV, texCoordUV).a);\n"
222
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
223
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).stAlpha, stTexture(uTextureV, texCoordUV).stAlpha);\n"
224
        "    colorYUV   *= TheRangeBits;\n"
225
        "    colorYUV.x  = colorYUV.x;\n"
226
        "    colorYUV.y -= 0.5;\n"
227
@@ -145,10 +247,27 @@
228
        "    color.b = colorYUV.x + 1.772 * colorYUV.y;\n"
229
        "}\n\n";
230
 
231
+    const char F_SHADER_YUVA2RGB_FULL[] =
232
+       "uniform stSampler uTextureU;\n"
233
+       "uniform stSampler uTextureV;\n"
234
+       "uniform stSampler uTextureA;\n"
235
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
236
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).stAlpha, stTexture(uTextureV, texCoordUV).stAlpha);\n"
237
+       "    colorYUV   *= TheRangeBits;\n"
238
+       "    colorYUV.x  = colorYUV.x;\n"
239
+       "    colorYUV.y -= 0.5;\n"
240
+       "    colorYUV.z -= 0.5;\n"
241
+       "    color.r = colorYUV.x + 1.402 * colorYUV.z;\n"
242
+       "    color.g = colorYUV.x - 0.344 * colorYUV.y - 0.714 * colorYUV.z;\n"
243
+       "    color.b = colorYUV.x + 1.772 * colorYUV.y;\n"
244
+       "    color.a = stTexture(uTextureA, texCoordA).stAlpha;\n" // TODO how to handle TheRangeBits?
245
+       "    drawAlphaBackground(color);\n"
246
+       "}\n\n";
247
+
248
     const char F_SHADER_YUVNV2RGB_MPEG[] =
249
        "uniform stSampler uTextureU;\n"
250
-       "void convertToRGB(inout vec4 color, in vec3 texCoordUV) {\n"
251
-       "    vec3 colorYUV = vec3(color.a, stTexture(uTextureU, texCoordUV).r, stTexture(uTextureU, texCoordUV).a);\n"
252
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
253
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).r, stTexture(uTextureU, texCoordUV).a);\n"
254
        "    colorYUV   *= TheRangeBits;\n"
255
        "    colorYUV.x  = 1.1643 * (colorYUV.x - 0.0625);\n"
256
        "    colorYUV.y -= 0.5;\n"
257
@@ -160,8 +279,8 @@
258
 
259
     const char F_SHADER_YUVNV2RGB_FULL[] =
260
        "uniform stSampler uTextureU;\n"
261
-       "void convertToRGB(inout vec4 color, in vec3 texCoordUV) {\n"
262
-       "    vec3 colorYUV = vec3(color.a, stTexture(uTextureU, texCoordUV).r, stTexture(uTextureU, texCoordUV).a);\n"
263
+       "void convertToRGB(inout vec4 color, in vec3 texCoordUV, in vec3 texCoordA) {\n"
264
+       "    vec3 colorYUV = vec3(color.stAlpha, stTexture(uTextureU, texCoordUV).r, stTexture(uTextureU, texCoordUV).a);\n"
265
        "    colorYUV   *= TheRangeBits;\n"
266
        "    colorYUV.x  = colorYUV.x;\n"
267
        "    colorYUV.y -= 0.5;\n"
268
@@ -171,75 +290,91 @@
269
        "    color.b = colorYUV.x + 1.772 * colorYUV.y;\n"
270
        "}\n\n";
271
 
272
-    regToRgb(FragToRgb_FromYuvFull, StString()
273
+    regToRgb(theCtx, FragToRgb_FromYuvFull, StString()
274
         + "const float TheRangeBits = 1.0;\n"
275
         + F_SHADER_YUV2RGB_FULL);
276
 
277
-    regToRgb(FragToRgb_FromYuvMpeg, StString()
278
+    regToRgb(theCtx, FragToRgb_FromYuvaFull, StString()
279
+        + "const float TheRangeBits = 1.0;\n"
280
+        + F_ALPHA_BACKGROUND
281
+        + F_SHADER_YUVA2RGB_FULL);
282
+
283
+    regToRgb(theCtx, FragToRgb_FromYuvMpeg, StString()
284
         + "const float TheRangeBits = 1.0;\n"
285
         + F_SHADER_YUV2RGB_MPEG);
286
 
287
-    regToRgb(FragToRgb_FromYuv9Full, StString()
288
+    regToRgb(theCtx, FragToRgb_FromYuvaMpeg, StString()
289
+        + "const float TheRangeBits = 1.0;\n"
290
+        + F_ALPHA_BACKGROUND
291
+        + F_SHADER_YUVA2RGB_MPEG);
292
+
293
+    regToRgb(theCtx, FragToRgb_FromYuv9Full, StString()
294
         + "const float TheRangeBits = 65535.0 / 511.0;\n"
295
         + F_SHADER_YUV2RGB_FULL);
296
 
297
-    regToRgb(FragToRgb_FromYuv9Mpeg, StString()
298
+    regToRgb(theCtx, FragToRgb_FromYuva9Full, StString()
299
+        + "const float TheRangeBits = 65535.0 / 511.0;\n"
300
+        + F_ALPHA_BACKGROUND
301
+        + F_SHADER_YUVA2RGB_FULL);
302
+
303
+    regToRgb(theCtx, FragToRgb_FromYuv9Mpeg, StString()
304
         + "const float TheRangeBits = 65535.0 / 511.0;\n"
305
         + F_SHADER_YUV2RGB_MPEG);
306
 
307
-    regToRgb(FragToRgb_FromYuv10Full, StString()
308
+    regToRgb(theCtx, FragToRgb_FromYuva9Mpeg, StString()
309
+        + "const float TheRangeBits = 65535.0 / 511.0;\n"
310
+        + F_ALPHA_BACKGROUND
311
+        + F_SHADER_YUVA2RGB_MPEG);
312
+
313
+    regToRgb(theCtx, FragToRgb_FromYuv10Full, StString()
314
         + "const float TheRangeBits = 65535.0 / 1023.0;\n"
315
         + F_SHADER_YUV2RGB_FULL);
316
 
317
-    regToRgb(FragToRgb_FromYuv10Mpeg, StString()
318
+    regToRgb(theCtx, FragToRgb_FromYuva10Full, StString()
319
+        + "const float TheRangeBits = 65535.0 / 1023.0;\n"
320
+        + F_ALPHA_BACKGROUND
321
+        + F_SHADER_YUVA2RGB_FULL);
322
+
323
+    regToRgb(theCtx, FragToRgb_FromYuv10Mpeg, StString()
324
         + "const float TheRangeBits = 65535.0 / 1023.0;\n"
325
         + F_SHADER_YUV2RGB_MPEG);
326
 
327
-    regToRgb(FragToRgb_FromYuvNvFull, StString()
328
+    regToRgb(theCtx, FragToRgb_FromYuva10Mpeg, StString()
329
+        + "const float TheRangeBits = 65535.0 / 1023.0;\n"
330
+        + F_ALPHA_BACKGROUND
331
+        + F_SHADER_YUVA2RGB_MPEG);
332
+
333
+    regToRgb(theCtx, FragToRgb_FromYuvNvFull, StString()
334
         + "const float TheRangeBits = 1.0;\n"
335
         + F_SHADER_YUVNV2RGB_FULL);
336
 
337
-    regToRgb(FragToRgb_FromYuvNvMpeg, StString()
338
+    regToRgb(theCtx, FragToRgb_FromYuvNvMpeg, StString()
339
         + "const float TheRangeBits = 1.0;\n"
340
         + F_SHADER_YUVNV2RGB_MPEG);
341
 
342
-    params.gamma = new StFloat32Param(1.0f);
343
-    params.gamma->setMinMaxValues(0.05f, 99.0f);
344
-    params.gamma->setEffectiveMinMaxValues(0.05f, 2.0f);
345
-    params.gamma->setDefValue(1.0f);
346
-    params.gamma->setStep(0.05f);
347
-    params.gamma->setTolerance(0.0001f);
348
-
349
-    params.brightness = new StFloat32Param(1.0f);
350
-    params.brightness->setMinMaxValues(0.0f, 99.0f);
351
-    params.brightness->setDefValue(1.0f);
352
-    params.brightness->setEffectiveMinMaxValues(0.0f, 5.0f);
353
-    params.brightness->setStep(0.05f);
354
-    params.brightness->setTolerance(0.0001f);
355
-
356
-    params.saturation = new StFloat32Param(1.0f);
357
-    params.saturation->setMinMaxValues(-10.0f, 99.0f);
358
-    params.saturation->setEffectiveMinMaxValues(0.0f, 2.0f);
359
-    params.saturation->setDefValue(1.0f);
360
-    params.saturation->setStep(0.05f);
361
-    params.saturation->setTolerance(0.0001f);
362
-
363
     // main shader parts
364
     const char V_SHADER_FLAT[] =
365
        "uniform mat4 uProjMat;\n"
366
        "uniform mat4 uModelMat;\n"
367
        "uniform vec4 uTexData;\n"
368
        "uniform vec4 uTexUVData;\n"
369
+       "uniform vec4 uTexAData;\n"
370
 
371
        "attribute vec4 vVertex;\n"
372
        "attribute vec2 vTexCoord;\n"
373
 
374
        "varying vec3 fTexCoord;\n"
375
        "varying vec3 fTexUVCoord;\n"
376
+       "varying vec3 fTexACoord;\n"
377
+       "varying vec3 fTexClamp;\n"
378
+       "varying float fTexClampW;\n"
379
 
380
        "void main(void) {\n"
381
        "    fTexCoord   = vec3(uTexData.xy   + vTexCoord * uTexData.zw,   0.0);\n"
382
        "    fTexUVCoord = vec3(uTexUVData.xy + vTexCoord * uTexUVData.zw, 0.0);\n"
383
+       "    fTexACoord  = vec3(uTexAData.xy  + vTexCoord * uTexAData.zw,  0.0);\n"
384
+       "    fTexClamp   = vec3(0.0, 0.0, 0.0);\n"
385
+       "    fTexClampW  = 0.0;\n"
386
        "    gl_Position = uProjMat * uModelMat * vVertex;\n"
387
        "}\n";
388
 
389
@@ -248,38 +383,55 @@
390
        "uniform mat4 uModelMat;\n"
391
        "uniform vec4 uTexData;\n"
392
        "uniform vec4 uTexUVData;\n"
393
+       "uniform vec4 uTexAData;\n"
394
        "uniform float uTexCubeFlipZ;\n"
395
 
396
        "attribute vec4 vVertex;\n"
397
-       "attribute vec2 vTexCoord;\n"
398
+       "attribute vec3 vNormal;\n"
399
+       "attribute vec4 vColor;\n"
400
 
401
        "varying vec3 fTexCoord;\n"
402
        "varying vec3 fTexUVCoord;\n"
403
+       "varying vec3 fTexACoord;\n"
404
+       "varying vec3 fTexClamp;\n"
405
+       "varying float fTexClampW;\n"
406
 
407
        "void main(void) {\n"
408
-       "    gl_Position = vec4(vVertex.x, vVertex.y, 0.0, 1.0);\n"
409
-       "    vec3 aTCoord = (uProjMat * gl_Position).xyz;"
410
-       "    aTCoord.z  *= uTexCubeFlipZ;"
411
-       "    fTexCoord   = aTCoord;"
412
-       "    fTexUVCoord = aTCoord;"
413
+       "    vec4 aPos = uProjMat * uModelMat * vec4(vVertex.xyz, 1.0);\n"
414
+       "    gl_Position = aPos.xyww;\n"
415
+       "    vec3 aTCoord = vNormal;\n" // fake normal attribute
416
+       "    aTCoord.z  *= uTexCubeFlipZ;\n"
417
+       "    fTexCoord   = aTCoord;\n"
418
+       "    fTexUVCoord = aTCoord;\n"
419
+       "    fTexACoord  = aTCoord;\n"
420
+       "    fTexClamp   = vColor.xyz;\n" // fake color attribute
421
+       "    fTexClampW  = vColor.w;\n"
422
        "}\n";
423
 
424
     const char F_SHADER_FLAT[] =
425
        "varying vec3 fTexCoord;\n"
426
        "varying vec3 fTexUVCoord;\n"
427
+       "varying vec3 fTexACoord;\n"
428
+       "varying vec3 fTexClamp;\n"
429
+       "varying float fTexClampW;\n"
430
         // we split these functions for two reasons:
431
         // - to change function code (like color conversion);
432
         // - to optimize rendering on old hardware not supported conditions (GeForce FX for example).
433
+       "vec3 getTexCoords(in vec3 theCoords, in vec4 theClamp);\n"
434
        "vec4 getColor(in vec3 texCoord);\n"
435
-       "void convertToRGB(inout vec4 theColor, in vec3 theTexUVCoord);\n"
436
+       "void convertToRGB(inout vec4 theColor, in vec3 theTexUVCoord, in vec3 texCoordA);\n"
437
        "void applyCorrection(inout vec4 theColor);\n"
438
        "void applyGamma(inout vec4 theColor);\n"
439
 
440
        "void main(void) {\n"
441
+       "    vec4 aTexClamp   = vec4(fTexClamp, fTexClampW);\n"
442
+       "    vec3 aTexCoord   = getTexCoords(fTexCoord,   aTexClamp);\n"
443
+       "    vec3 aTexCoordUV = getTexCoords(fTexUVCoord, aTexClamp);\n"
444
+       "    vec3 aTexCoordA  = getTexCoords(fTexACoord,  aTexClamp);\n"
445
             // extract color from main texture
446
-       "    vec4 aColor = getColor(fTexCoord);\n"
447
+       "    vec4 aColor = getColor(aTexCoord);\n"
448
             // convert from alien color model (like YUV) to RGB
449
-       "    convertToRGB(aColor, fTexUVCoord);\n"
450
+       "    convertToRGB(aColor, aTexCoordUV, aTexCoordA);\n"
451
             // color processing (saturation, brightness, etc)
452
        "    applyCorrection(aColor);\n"
453
             // gamma correction
454
@@ -312,6 +464,11 @@
455
     theCtx.core20fwd->glUniform4fv(uniTexUVDataLoc, 1, theTexDataVec4);
456
 }
457
 
458
+void StGLImageProgram::setTextureADataSize(StGLContext&    theCtx,
459
+                                           const StGLVec4& theTexDataVec4) {
460
+  theCtx.core20fwd->glUniform4fv(uniTexADataLoc, 1, theTexDataVec4);
461
+}
462
+
463
 void StGLImageProgram::setCubeTextureFlipZ(StGLContext& theCtx,
464
                                            bool theToFlip) {
465
     theCtx.core20fwd->glUniform1f(uniTexCubeFlipZLoc, theToFlip ? 1.0f : -1.0f);
466
@@ -341,18 +498,20 @@
467
         case StImage::ImgColor_RGBA: return StGLImageProgram::FragToRgb_FromRgba;
468
         case StImage::ImgColor_GRAY: return StGLImageProgram::FragToRgb_FromGray;
469
         case StImage::ImgColor_XYZ:  return StGLImageProgram::FragToRgb_FromXyz;
470
-        case StImage::ImgColor_YUV: {
471
+        case StImage::ImgColor_YUV:
472
+        case StImage::ImgColor_YUVA: {
473
+            const bool hasAlpha = theColorModel == StImage::ImgColor_YUVA;
474
             switch(theColorScale) {
475
-                case StImage::ImgScale_Mpeg9:  return StGLImageProgram::FragToRgb_FromYuv9Mpeg;
476
-                case StImage::ImgScale_Mpeg10: return StGLImageProgram::FragToRgb_FromYuv10Mpeg;
477
-                case StImage::ImgScale_Jpeg9:  return StGLImageProgram::FragToRgb_FromYuv9Full;
478
-                case StImage::ImgScale_Jpeg10: return StGLImageProgram::FragToRgb_FromYuv10Full;
479
-                case StImage::ImgScale_Mpeg:   return StGLImageProgram::FragToRgb_FromYuvMpeg;
480
-                case StImage::ImgScale_Full:   return StGLImageProgram::FragToRgb_FromYuvFull;
481
+                case StImage::ImgScale_Mpeg9:  return hasAlpha ? StGLImageProgram::FragToRgb_FromYuva9Mpeg  : StGLImageProgram::FragToRgb_FromYuv9Mpeg;
482
+                case StImage::ImgScale_Mpeg10: return hasAlpha ? StGLImageProgram::FragToRgb_FromYuva10Mpeg : StGLImageProgram::FragToRgb_FromYuv10Mpeg;
483
+                case StImage::ImgScale_Jpeg9:  return hasAlpha ? StGLImageProgram::FragToRgb_FromYuva9Full  : StGLImageProgram::FragToRgb_FromYuv9Full;
484
+                case StImage::ImgScale_Jpeg10: return hasAlpha ? StGLImageProgram::FragToRgb_FromYuva10Full : StGLImageProgram::FragToRgb_FromYuv10Full;
485
+                case StImage::ImgScale_Mpeg:   return hasAlpha ? StGLImageProgram::FragToRgb_FromYuvaMpeg   : StGLImageProgram::FragToRgb_FromYuvMpeg;
486
+                case StImage::ImgScale_Full:   return hasAlpha ? StGLImageProgram::FragToRgb_FromYuvaFull   : StGLImageProgram::FragToRgb_FromYuvFull;
487
                 case StImage::ImgScale_NvMpeg: return StGLImageProgram::FragToRgb_FromYuvNvMpeg;
488
                 case StImage::ImgScale_NvFull: return StGLImageProgram::FragToRgb_FromYuvNvFull;
489
             }
490
-            return StGLImageProgram::FragToRgb_FromYuvFull;
491
+            return hasAlpha ? StGLImageProgram::FragToRgb_FromYuvaFull : StGLImageProgram::FragToRgb_FromYuvFull;
492
         }
493
         default: {
494
             ST_DEBUG_LOG("No GLSL shader for this color model = " + theColorModel);
495
@@ -365,7 +524,9 @@
496
 bool StGLImageProgram::init(StGLContext&                 theCtx,
497
                             const StImage::ImgColorModel theColorModel,
498
                             const StImage::ImgColorScale theColorScale,
499
-                            const FragGetColor           theFilter) {
500
+                            const FragGetColor           theFilter,
501
+                            const FragTexEAC theTexCoord) {
502
+    registerFragments(theCtx);
503
 
504
     // re-configure shader parts when required
505
     bool isChanged = myActiveProgram.isNull();
506
@@ -383,6 +544,7 @@
507
     }
508
 
509
     isChanged = setFragmentShaderPart(theCtx, FragSection_ToRgb,    aToRgb) || isChanged;
510
+    isChanged = setFragmentShaderPart(theCtx, FragSection_GetTexCoords, theTexCoord) || isChanged;
511
     isChanged = setFragmentShaderPart(theCtx, FragSection_GetColor, theFilter) || isChanged;
512
     isChanged = setVertexShaderPart  (theCtx, 0, theFilter == FragGetColor_Cubemap ? VertMain_Cubemap : VertMain_Normal) || isChanged;
513
     if(isChanged) {
514
@@ -394,6 +556,7 @@
515
         myActiveProgram->uniModelMatLoc = myActiveProgram->getUniformLocation(theCtx, "uModelMat");
516
         uniTexMainDataLoc     = myActiveProgram->getUniformLocation(theCtx, "uTexData");
517
         uniTexUVDataLoc       = myActiveProgram->getUniformLocation(theCtx, "uTexUVData");
518
+        uniTexADataLoc        = myActiveProgram->getUniformLocation(theCtx, "uTexAData");
519
         uniTexSizePxLoc       = myActiveProgram->getUniformLocation(theCtx, "uTexSizePx");
520
         uniTexelSizePxLoc     = myActiveProgram->getUniformLocation(theCtx, "uTexelSize");
521
         uniTexCubeFlipZLoc    = myActiveProgram->getUniformLocation(theCtx, "uTexCubeFlipZ");
522
@@ -401,14 +564,18 @@
523
         uniGammaLoc           = myActiveProgram->getUniformLocation(theCtx, "uGamma");
524
         myActiveProgram->atrVVertexLoc  = myActiveProgram->getAttribLocation(theCtx, "vVertex");
525
         myActiveProgram->atrVTCoordLoc  = myActiveProgram->getAttribLocation(theCtx, "vTexCoord");
526
+        myActiveProgram->atrVNormalLoc  = myActiveProgram->getAttribLocation(theCtx, "vNormal");
527
+        myActiveProgram->atrVColorsLoc  = myActiveProgram->getAttribLocation(theCtx, "vColor");
528
 
529
         StGLVarLocation uniTextureLoc  = myActiveProgram->getUniformLocation(theCtx, "uTexture");
530
         StGLVarLocation uniTextureULoc = myActiveProgram->getUniformLocation(theCtx, "uTextureU");
531
         StGLVarLocation uniTextureVLoc = myActiveProgram->getUniformLocation(theCtx, "uTextureV");
532
+        StGLVarLocation uniTextureALoc = myActiveProgram->getUniformLocation(theCtx, "uTextureA");
533
         myActiveProgram->use(theCtx);
534
         theCtx.core20fwd->glUniform1i(uniTextureLoc,  StGLProgram::TEXTURE_SAMPLE_0);
535
         theCtx.core20fwd->glUniform1i(uniTextureULoc, StGLProgram::TEXTURE_SAMPLE_1);
536
         theCtx.core20fwd->glUniform1i(uniTextureVLoc, StGLProgram::TEXTURE_SAMPLE_2);
537
+        theCtx.core20fwd->glUniform1i(uniTextureALoc, StGLProgram::TEXTURE_SAMPLE_3);
538
         myActiveProgram->unuse(theCtx);
539
 
540
         /*if (!uniModelMatLoc.isValid()
541
sview-17_04.tar.gz/StGLWidgets/StGLImageRegion.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLImageRegion.cpp Changed
942
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2016 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -9,6 +9,7 @@
10
 
11
 #include <StGLWidgets/StGLImageRegion.h>
12
 #include <StGLWidgets/StGLRootWidget.h>
13
+#include <StGLWidgets/StGLTextureButton.h>
14
 #include <StGL/StPlayList.h>
15
 #include <StGLStereo/StGLQuadTexture.h>
16
 
17
@@ -202,20 +203,30 @@
18
 
19
     // we use negative scale factor to show sphere inside out!
20
     static const float THE_SPHERE_RADIUS     = -10.0f;
21
-    static const float THE_PANORAMA_DEF_ZOOM = 0.45f;
22
+    static const float THE_PANORAMA_DEF_ZOOM = 0.45f; // circa 85 degrees FOV
23
 
24
+    static const float THE_THEATER_ANGLE = float(M_PI * 0.5);
25
+    static const float THE_THEATER_FROM  = float(M_PI) - THE_THEATER_ANGLE * 0.5f;
26
 }
27
 
28
 StGLImageRegion::StGLImageRegion(StGLWidget* theParent,
29
                                  const StHandle<StGLTextureQueue>& theTextureQueue,
30
                                  bool theUsePanningKeys)
31
 : StGLWidget(theParent, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT)),
32
-  myQuad(),
33
-  myUVSphere(StGLVec3(0.0f, 0.0f, 0.0f), 1.0f, 64),
34
+  myIconPrev(NULL),
35
+  myIconNext(NULL),
36
+  myCube(GL_TRIANGLES),
37
+  myCubePano(StPanorama_OFF),
38
+  myUVSphere  (StGLVec3(0.0f, 0.0f, 0.0f), 1.0f, 64, false),
39
+  myHemisphere(StGLVec3(0.0f, 0.0f, 0.0f), 1.0f, 64, true),
40
+  myCylinder  (StGLVec3(0.0f, 0.0f, 0.0f), 1.0f, 1.0f, 64),
41
+  myTheater   (StGLVec3(0.0f, 0.0f, 0.0f), 1.0f, 1.0f, THE_THEATER_FROM, THE_THEATER_FROM + THE_THEATER_ANGLE, 64),
42
   myTextureQueue(theTextureQueue),
43
   myClickPntZo(0.0, 0.0),
44
   myKeyFlags(ST_VF_NONE),
45
   myDragDelayMs(0.0),
46
+  myDragDelayTmpMs(0.0),
47
+  mySampleRatio(1.0f),
48
   myRotAngle(0.0f),
49
   myIsClickAborted(false),
50
 #ifdef ST_EXTRA_CONTROLS
51
@@ -225,6 +236,11 @@
52
 #endif
53
   myIsInitialized(false),
54
   myHasVideoStream(false) {
55
+    myIconPrev = new StGLIcon(this,  getRoot()->scale(48), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_LEFT),  1);
56
+    myIconPrev->setOpacity(0.0f, false);
57
+    myIconNext = new StGLIcon(this, -getRoot()->scale(48), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT), 1);
58
+    myIconNext->setOpacity(0.0f, false);
59
+
60
     params.DisplayMode = new StEnumParam(MODE_STEREO, stCString("viewStereoMode"), stCString("Stereo Output"));
61
     params.DisplayMode->defineOption(MODE_STEREO,     stCString("Stereo"));
62
     params.DisplayMode->defineOption(MODE_ONLY_LEFT,  stCString("Left View"));
63
@@ -243,9 +259,10 @@
64
 
65
     params.ToHealAnamorphicRatio = new StBoolParamNamed(false, stCString("toHealAnamorphic"), stCString("Heal Anamorphic Ratio"));
66
     params.TextureFilter = new StEnumParam(StGLImageProgram::FILTER_LINEAR, stCString("viewTexFilter"), stCString("Texture Filter"));
67
-    params.TextureFilter->defineOption(StGLImageProgram::FILTER_NEAREST, stCString("Nearest"));
68
-    params.TextureFilter->defineOption(StGLImageProgram::FILTER_LINEAR,  stCString("Linear"));
69
-    params.TextureFilter->defineOption(StGLImageProgram::FILTER_BLEND,   stCString("Blend"));
70
+    params.TextureFilter->defineOption(StGLImageProgram::FILTER_NEAREST,   stCString("Nearest"));
71
+    params.TextureFilter->defineOption(StGLImageProgram::FILTER_LINEAR,    stCString("Linear"));
72
+    params.TextureFilter->defineOption(StGLImageProgram::FILTER_TRILINEAR, stCString("Trilinear"));
73
+    params.TextureFilter->defineOption(StGLImageProgram::FILTER_BLEND,     stCString("Blend"));
74
 
75
     params.Gamma         = myProgram.params.gamma;
76
     params.Brightness    = myProgram.params.brightness;
77
@@ -393,7 +410,11 @@
78
     StGLContext& aCtx = getContext();
79
     myTextureQueue->getQTexture().release(aCtx);
80
     myQuad.release(aCtx);
81
+    myCube.release(aCtx);
82
     myUVSphere.release(aCtx);
83
+    myHemisphere.release(aCtx);
84
+    myCylinder.release(aCtx);
85
+    myTheater.release(aCtx);
86
     myProgram.release(aCtx);
87
 
88
     // simplify debugging - nullify pointer to this widget
89
@@ -420,7 +441,10 @@
90
         StHandle<StStereoParams> aFileParams = myTextureQueue->getQTexture().getFront(StGLQuadTexture::LEFT_TEXTURE).getSource();
91
         if(params.stereoFile != aFileParams) {
92
             params.stereoFile = aFileParams;
93
+            myFadeTimer.stop();
94
             onParamsChanged();
95
+        } else if(!myHasVideoStream) {
96
+            myFadeTimer.stop();
97
         }
98
     }
99
 }
100
@@ -438,17 +462,182 @@
101
         aCtx.pushError(StString("Fail to init StGLQuad"));
102
         ST_ERROR_LOG("Fail to init StGLQuad");
103
         return false;
104
-    } else if(!myUVSphere.initVBOs(aCtx)) {
105
+    }/* else if(!myUVSphere.initVBOs(aCtx)) {
106
         ST_ERROR_LOG("Fail to init StGLUVSphere");
107
+    }*/
108
+
109
+    // a unit cube for cubemap rendering
110
+    if(!stglInitCube()) {
111
+        return false;
112
     }
113
 
114
     // setup texture filter
115
-    myTextureQueue->getQTexture().setMinMagFilter(aCtx, params.TextureFilter->getValue() == StGLImageProgram::FILTER_NEAREST ? GL_NEAREST : GL_LINEAR);
116
+    myTextureQueue->getQTexture().setMinMagFilter(aCtx,
117
+                                                  params.TextureFilter->getValue() == StGLImageProgram::FILTER_NEAREST
118
+                                                ? GL_NEAREST : GL_LINEAR);
119
 
120
     myIsInitialized = true;
121
     return myIsInitialized && isInit;
122
 }
123
 
124
+/**
125
+ * Cubemap sides.
126
+ */
127
+enum StCubeSide {
128
+    StCubeSide_PX = 0,
129
+    StCubeSide_NX,
130
+    StCubeSide_PY,
131
+    StCubeSide_NY,
132
+    StCubeSide_PZ,
133
+    StCubeSide_NZ,
134
+};
135
+typedef StVec4<int> StIVec4;
136
+
137
+bool StGLImageRegion::stglInitCube(const StGLVec4& theClamp,
138
+                                   const StPanorama thePano) {
139
+    myCubeClamp = theClamp;
140
+    myCubePano = thePano;
141
+
142
+    // a unit cube for cubemap rendering
143
+    const StGLVec3 THE_VERTS[8] = {
144
+        StGLVec3(-1.0f,-1.0f, 1.0f),
145
+        StGLVec3( 1.0f,-1.0f, 1.0f),
146
+        StGLVec3(-1.0f, 1.0f, 1.0f),
147
+        StGLVec3( 1.0f, 1.0f, 1.0f),
148
+        StGLVec3(-1.0f,-1.0f,-1.0f),
149
+        StGLVec3( 1.0f,-1.0f,-1.0f),
150
+        StGLVec3(-1.0f, 1.0f,-1.0f),
151
+        StGLVec3( 1.0f, 1.0f,-1.0f)
152
+    };
153
+
154
+    const StIVec4 THE_SIDES[6] = {
155
+        StIVec4(3, 7, 5, 1), // px
156
+        StIVec4(6, 2, 0, 4), // nx
157
+        StIVec4(2, 3, 7, 6), // py
158
+        StIVec4(0, 1, 5, 4), // ny
159
+        StIVec4(0, 1, 3, 2), // pz
160
+        StIVec4(5, 4, 6, 7), // nz
161
+    };
162
+
163
+    StArrayList<StGLVec3>& aVertArr  = myCube.changeVertices();
164
+    StArrayList<StGLVec3>& aCoordArr = myCube.changeNormals();
165
+    StArrayList<StGLVec4>& aClampArr = myCube.changeColors();
166
+    aVertArr.initArray(6 * 6);
167
+    aCoordArr.initArray(aVertArr.size());
168
+    aClampArr.initArray(aVertArr.size());
169
+    int aVert = 0;
170
+    for(int aSideIter = 0; aSideIter < 6; ++aSideIter, aVert += 6) {
171
+        StIVec4 aSide = THE_SIDES[aSideIter];
172
+        aVertArr[aVert + 0] = THE_VERTS[aSide[0]];
173
+        aVertArr[aVert + 1] = THE_VERTS[aSide[1]];
174
+        aVertArr[aVert + 2] = THE_VERTS[aSide[2]];
175
+
176
+        aVertArr[aVert + 3] = THE_VERTS[aSide[0]];
177
+        aVertArr[aVert + 4] = THE_VERTS[aSide[2]];
178
+        aVertArr[aVert + 5] = THE_VERTS[aSide[3]];
179
+
180
+        // rotate EAC cube sides
181
+        if(thePano == StPanorama_Cubemap3_2ytb) {
182
+            if(aSideIter == StCubeSide_NY) {
183
+                const StIVec4 aCopy = aSide;
184
+                for(int aSubIter = 0; aSubIter < 4; ++aSubIter) {
185
+                    aSide[aSubIter] = aCopy[aSubIter > 0 ? aSubIter - 1 : 3];
186
+                }
187
+            }
188
+            if(aSideIter == StCubeSide_NZ || aSideIter == StCubeSide_PY) {
189
+                const StIVec4 aCopy = aSide;
190
+                for(int aSubIter = 0; aSubIter < 4; ++aSubIter) {
191
+                    aSide[aSubIter] = aCopy[aSubIter < 3 ? aSubIter + 1 : 0];
192
+                }
193
+            }
194
+        } else if(thePano == StPanorama_Cubemap2_3ytb) {
195
+            if(aSideIter == StCubeSide_PX
196
+            || aSideIter == StCubeSide_NX) {
197
+                const StIVec4 aCopy = aSide;
198
+                for(int aSubIter = 0; aSubIter < 4; ++aSubIter) {
199
+                    aSide[aSubIter] = aCopy[aSubIter < 3 ? aSubIter + 1 : 0];
200
+                }
201
+            }
202
+            if(aSideIter == StCubeSide_PZ) {
203
+                const StIVec4 aCopy = aSide;
204
+                for(int aSubIter = 0; aSubIter < 4; ++aSubIter) {
205
+                    aSide[aSubIter] = aCopy[aSubIter > 0 ? aSubIter - 1 : 3];
206
+                }
207
+            }
208
+        }
209
+
210
+        aCoordArr[aVert + 0] = THE_VERTS[aSide[0]];
211
+        aCoordArr[aVert + 1] = THE_VERTS[aSide[1]];
212
+        aCoordArr[aVert + 2] = THE_VERTS[aSide[2]];
213
+
214
+        aCoordArr[aVert + 3] = THE_VERTS[aSide[0]];
215
+        aCoordArr[aVert + 4] = THE_VERTS[aSide[2]];
216
+        aCoordArr[aVert + 5] = THE_VERTS[aSide[3]];
217
+        for(int aSubIter = 0; aSubIter < 6; ++aSubIter) {
218
+            StGLVec4& aClamp = aClampArr[aVert + aSubIter];
219
+            aClamp = StGLVec4(0.0f, 0.0f, 0.0f, theClamp.x());
220
+            switch(aSideIter) {
221
+                case StCubeSide_PX: {
222
+                    aClamp.x() = 1.0f;
223
+                    aClamp.y() = -theClamp.w();
224
+                    aClamp.z() = -theClamp.z();
225
+                    break;
226
+                }
227
+                case StCubeSide_NX: {
228
+                    aClamp.x() = -1.0f;
229
+                    aClamp.y() = -theClamp.w();
230
+                    aClamp.z() = theClamp.z();
231
+                    break;
232
+                }
233
+                case StCubeSide_PZ: {
234
+                    aClamp.x() = -theClamp.z();
235
+                    aClamp.y() = -theClamp.w();
236
+                    aClamp.z() = 1.0f;
237
+                    break;
238
+                }
239
+                case StCubeSide_NZ: {
240
+                    aClamp.x() = theClamp.z();
241
+                    aClamp.y() = -theClamp.w();
242
+                    aClamp.z() = -1.0f;
243
+                    break;
244
+                }
245
+                case StCubeSide_PY: {
246
+                    aClamp.x() = theClamp.z();
247
+                    aClamp.y() = 1.0f;
248
+                    aClamp.z() = theClamp.w();
249
+                    break;
250
+                }
251
+                case StCubeSide_NY: {
252
+                    aClamp.x() = theClamp.z();
253
+                    aClamp.y() = -1.0f;
254
+                    aClamp.z() = -theClamp.w();
255
+                    break;
256
+                }
257
+            }
258
+        }
259
+    }
260
+
261
+    // triangle strip initialization
262
+    /*aCubeVerts.initArray(8);
263
+    for(int aVertIter = 0; aVertIter < 8; ++aVertIter) {
264
+      aCubeVerts[aVertIter] = THE_VERTS[aVertIter];
265
+    }
266
+    const GLuint THE_BOX_TRISTRIP[14] = { 0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1 };
267
+    StArrayList<GLuint>& aCubeInd = myCube.changeIndices();
268
+    aCubeInd.initArray(14);
269
+    for(unsigned int aVertIter = 0; aVertIter < 14; ++aVertIter) {
270
+        aCubeInd[aVertIter] = THE_BOX_TRISTRIP[aVertIter];
271
+    }*/
272
+
273
+    StGLContext& aCtx = getContext();
274
+    if(!myCube.initVBOs(aCtx)) {
275
+        aCtx.pushError(StString("Fail to init Cube Mesh"));
276
+        ST_ERROR_LOG("Fail to init Cube Mesh");
277
+        return false;
278
+    }
279
+    return true;
280
+}
281
+
282
 StGLVec2 StGLImageRegion::getMouseMoveFlat(const StPointD_t& theCursorZoFrom,
283
                                            const StPointD_t& theCursorZoTo) const {
284
     // apply scale factor in case of working area margins
285
@@ -491,6 +680,9 @@
286
     float aYaw   = -stToRadians(aParams->getPanYaw() + aMouseMove.x()) + aYawShift;
287
     float aPitch =  stToRadians(StStereoParams::clipPitch(aParams->getPanPitch() + aMouseMove.y()));
288
     float aRoll  =  stToRadians(aParams->getZRotate());
289
+    if(myProjCam.isCustomProjection()) {
290
+        aPitch = 0.0f; // ignore pitch for HMD
291
+    }
292
 
293
     // apply separation
294
     const float aSepDeltaX = GLfloat(aParams->getSeparationDx()) * 0.05f;
295
@@ -516,6 +708,8 @@
296
 }
297
 
298
 void StGLImageRegion::stglDraw(unsigned int theView) {
299
+    myIconPrev->setOpacity(0.0f, false);
300
+    myIconNext->setOpacity(0.0f, false);
301
     StHandle<StStereoParams> aParams = getSource();
302
     if(!myIsInitialized || !isVisible() || aParams.isNull()
303
     || !myTextureQueue->getQTexture().getFront(StGLQuadTexture::LEFT_TEXTURE).isValid()
304
@@ -551,6 +745,8 @@
305
 void StGLImageRegion::stglDrawView(unsigned int theView) {
306
     StGLQuadTexture::LeftOrRight aLeftOrRight = StGLQuadTexture::LEFT_TEXTURE;
307
     StHandle<StStereoParams> aParams = getSource();
308
+    mySampleRatio = 1.0f;
309
+    myFrameSize = StVec2<int>(0, 0);
310
     if(!myIsInitialized || aParams.isNull()) {
311
         return;
312
     }
313
@@ -594,26 +790,24 @@
314
         }
315
     }
316
 
317
-    // setup scissor box
318
-    StGLBoxPx aScissorBox;
319
-    const StRectI_t aFrameRectAbs = getAbsolute(aFrameRectPx);
320
-    getRoot()->stglScissorRect(aFrameRectAbs, aScissorBox);
321
-    aCtx.stglSetScissorRect(aScissorBox, true);
322
-    aCtx.stglResizeViewport(aScissorBox);
323
+    // set 85 degrees FOV as 1.0x zoom for panorama rendering
324
+    myProjCam = *getCamera();
325
     myProjCam.resize(aCameraAspect);
326
+    myProjCam.setFOVy(85.0f);
327
 
328
     aCtx.core20fwd->glDisable(GL_BLEND);
329
 
330
     StGLFrameTextures& aTextures = myTextureQueue->getQTexture().getFront(aLeftOrRight);
331
-    aTextures.bind(aCtx);
332
 
333
     StGLVec2 aTextureSize  (GLfloat(aTextures.getPlane(0).getSizeX()),
334
                             GLfloat(aTextures.getPlane(0).getSizeY()));
335
     StGLVec2 aTextureUVSize(GLfloat(aTextures.getPlane(1).getSizeX()),
336
                             GLfloat(aTextures.getPlane(1).getSizeY()));
337
+    StGLVec2 aTextureASize (GLfloat(aTextures.getPlane(3).getSizeX()),
338
+                            GLfloat(aTextures.getPlane(3).getSizeY()));
339
     StGLMatrix aModelMat;
340
     // data rectangle in the texture
341
-    StGLVec4 aClampVec, aClampUV;
342
+    StGLVec4 aClampVec(0.0f, 0.0f, 1.0f, 1.0f), aClampUV(0.0f, 0.0f, 1.0f, 1.0f), aClampA(0.0f, 0.0f, 1.0f, 1.0f);
343
     if(params.TextureFilter->getValue() == StGLImageProgram::FILTER_NEAREST) {
344
         myTextureQueue->getQTexture().setMinMagFilter(aCtx, GL_NEAREST);
345
         //
346
@@ -626,22 +820,57 @@
347
         aClampUV.y() = 0.0f;
348
         aClampUV.z() = aTextures.getPlane(1).getDataSize().x();
349
         aClampUV.w() = aTextures.getPlane(1).getDataSize().y();
350
+        // Alpha
351
+        aClampA.x() = 0.0f;
352
+        aClampA.y() = 0.0f;
353
+        aClampA.z() = aTextures.getPlane(3).getDataSize().x();
354
+        aClampA.w() = aTextures.getPlane(3).getDataSize().y();
355
     } else {
356
-        myTextureQueue->getQTexture().setMinMagFilter(aCtx, GL_LINEAR);
357
-        //
358
-        aClampVec.x() = 0.5f / aTextureSize.x();
359
-        aClampVec.y() = 0.5f / aTextureSize.y();
360
-        aClampVec.z() = aTextures.getPlane(0).getDataSize().x() - 2.0f * aClampVec.x();
361
-        aClampVec.w() = aTextures.getPlane(0).getDataSize().y() - 2.0f * aClampVec.y();
362
+        if(params.TextureFilter->getValue() == StGLImageProgram::FILTER_TRILINEAR) {
363
+            myTextureQueue->getQTexture().setMinMagFilter(aCtx, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
364
+        } else {
365
+            myTextureQueue->getQTexture().setMinMagFilter(aCtx, GL_LINEAR);
366
+        }
367
+
368
+        // clamping is undesired for full-range cubemap to allow smooth seamless cube boundaries,
369
+        // but EAC video normally defines non-square cube sides requiring clamping
370
+        const bool isCubemapFull = aTextures.getPlane().getTarget() == GL_TEXTURE_CUBE_MAP
371
+                                && aTextures.getPlane().getPackedPanorama() != StPanorama_Cubemap3_2ytb
372
+                                && aTextures.getPlane().getPackedPanorama() != StPanorama_Cubemap2_3ytb;
373
+        if(!isCubemapFull
374
+         || aTextures.getPlane(0).getDataSize().x() != aTextures.getPlane(0).getDataSize().y()
375
+         || aTextures.getPlane(0).getDataSize().x() != 1.0f) {
376
+            aClampVec.x() = 0.5f / aTextureSize.x();
377
+            aClampVec.y() = 0.5f / aTextureSize.y();
378
+            aClampVec.z() = aTextures.getPlane(0).getDataSize().x() - 2.0f * aClampVec.x();
379
+            aClampVec.w() = aTextures.getPlane(0).getDataSize().y() - 2.0f * aClampVec.y();
380
+        }
381
         // UV
382
         if(aTextureUVSize.x() > 0.0f
383
         && aTextureUVSize.y() > 0.0f) {
384
-            aClampUV.x() = 0.5f / aTextureUVSize.x();
385
-            aClampUV.y() = 0.5f / aTextureUVSize.y(),
386
-            aClampUV.z() = aTextures.getPlane(1).getDataSize().x() - 2.0f * aClampUV.x();
387
-            aClampUV.w() = aTextures.getPlane(1).getDataSize().y() - 2.0f * aClampUV.y();
388
+            if(!isCubemapFull
389
+             || aTextures.getPlane(1).getDataSize().x() != aTextures.getPlane(1).getDataSize().y()
390
+             || aTextures.getPlane(1).getDataSize().x() != 1.0f) {
391
+                aClampUV.x() = 0.5f / aTextureUVSize.x();
392
+                aClampUV.y() = 0.5f / aTextureUVSize.y(),
393
+                aClampUV.z() = aTextures.getPlane(1).getDataSize().x() - 2.0f * aClampUV.x();
394
+                aClampUV.w() = aTextures.getPlane(1).getDataSize().y() - 2.0f * aClampUV.y();
395
+            }
396
+        }
397
+        // Alpha
398
+        if(aTextureASize.x() > 0.0f
399
+        && aTextureASize.y() > 0.0f) {
400
+            if(!isCubemapFull
401
+             || aTextures.getPlane(3).getDataSize().x() != aTextures.getPlane(3).getDataSize().y()
402
+             || aTextures.getPlane(3).getDataSize().x() != 1.0f) {
403
+                aClampA.x() = 0.5f / aTextureASize.x();
404
+                aClampA.y() = 0.5f / aTextureASize.y(),
405
+                aClampA.z() = aTextures.getPlane(3).getDataSize().x() - 2.0f * aClampA.x();
406
+                aClampA.w() = aTextures.getPlane(3).getDataSize().y() - 2.0f * aClampA.y();
407
+            }
408
         }
409
     }
410
+    aTextures.bind(aCtx);
411
 
412
     // select (de)anaglyph color filter
413
     StGLVec3 aColorScale(1.0f, 1.0f, 1.0f);
414
@@ -680,63 +909,129 @@
415
     const GLfloat  aScaleBack = aParams->ScaleFactor;
416
     const StGLVec2 aPanBack   = aParams->PanCenter;
417
 
418
-    const float aVrScale = float(myRoot->getVrZoomOut());
419
-
420
     StViewSurface aViewMode = aParams->ViewingMode;
421
     if(aTextures.getPlane(0).getTarget() == GL_TEXTURE_CUBE_MAP) {
422
-        aViewMode = StViewSurface_Cubemap;
423
-    } else if(aViewMode == StViewSurface_Cubemap) {
424
+        if(aViewMode != StViewSurface_Cubemap && aViewMode != StViewSurface_CubemapEAC) {
425
+            aViewMode = aTextures.getPlane().getPackedPanorama() == StPanorama_Cubemap3_2ytb
426
+                     || aTextures.getPlane().getPackedPanorama() == StPanorama_Cubemap2_3ytb
427
+                      ? StViewSurface_CubemapEAC
428
+                      : StViewSurface_Cubemap;
429
+        }
430
+    } else if(aViewMode == StViewSurface_Cubemap || aViewMode == StViewSurface_CubemapEAC) {
431
         aViewMode = StViewSurface_Plain;
432
     }
433
 
434
+    // setup scissor box
435
+    StGLBoxPx aScissorBox;
436
+    const StRectI_t aFrameRectAbs = getAbsolute(aFrameRectPx);
437
+    if(aViewMode == StViewSurface_Plain) {
438
+        getRoot()->stglScissorRect2d(aFrameRectAbs, aScissorBox);
439
+    } else {
440
+        getRoot()->stglScissorRect3d(aFrameRectAbs, aScissorBox);
441
+    }
442
+    aCtx.stglSetScissorRect(aScissorBox, true);
443
+    aCtx.stglResizeViewport(aScissorBox);
444
+
445
+    myFrameSize.x() = int(double(aTextures.getPlane().getDataSize().x()) * double(aTextures.getPlane().getSizeX()));
446
+    myFrameSize.y() = int(double(aTextures.getPlane().getDataSize().y()) * double(aTextures.getPlane().getSizeY()));
447
+    mySampleRatio = aTextures.getPlane().getPixelRatio();
448
+
449
     myProgram.setColorScale(aColorScale); // apply de-anaglyph color filter
450
     StGLImageProgram::FragGetColor aColorGetter = params.TextureFilter->getValue() == StGLImageProgram::FILTER_BLEND
451
                                                 ? StGLImageProgram::FragGetColor_Blend
452
                                                 : StGLImageProgram::FragGetColor_Normal;
453
+    const bool toDragImageInSwipe = getRectPx().ratio() < 0.75; // drag image only in portrait mode while swiping
454
     switch(aViewMode) {
455
         case StViewSurface_Plain: {
456
-            if(!myProgram.init(aCtx, aTextures.getColorModel(), aTextures.getColorScale(), aColorGetter)) {
457
-                break;
458
-            }
459
-
460
-            myProgram.getActiveProgram()->use(aCtx);
461
-
462
-            // setup data rectangle in the texture
463
-            myProgram.setTextureSizePx      (aCtx, aTextureSize);
464
-            myProgram.setTextureMainDataSize(aCtx, aClampVec);
465
-            myProgram.setTextureUVDataSize  (aCtx, aClampUV);
466
-
467
-            // handle dragging timer
468
-            if( isClicked(ST_MOUSE_LEFT)
469
-            && !myIsClickAborted
470
-            &&  myClickTimer.isOn()) {
471
-                if(myClickTimer.getElapsedTimeInMilliSec() < myDragDelayMs) {
472
-                    const StPointD_t aCurr = getRoot()->getCursorZo();
473
-                    const int aDx = int((aCurr.x() - myClickPntZo.x()) * double(getRectPx().width()));
474
-                    const int aDy = int((aCurr.y() - myClickPntZo.y()) * double(getRectPx().height()));
475
-                    if(std::abs(aDx) > myRoot->getClickThreshold()
476
-                    || std::abs(aDy) > myRoot->getClickThreshold()) {
477
-                        myIsClickAborted = true;
478
+            const float aBrightnessBack = params.Brightness->getValue();
479
+            const double aDragDelayMs = myDragDelayMs > 0.0 ? myDragDelayMs : myDragDelayTmpMs;
480
+            if(isClicked(ST_MOUSE_LEFT)) {
481
+                // handle dragging timer
482
+                if(!myIsClickAborted
483
+                &&  myClickTimer.isOn()) {
484
+                    if(myClickTimer.getElapsedTimeInMilliSec() < aDragDelayMs) {
485
+                        const StPointD_t aCurr = getRoot()->getCursorZo();
486
+                        const int aDx = int((aCurr.x() - myClickPntZo.x()) * double(getRectPx().width()));
487
+                        const int aDy = int((aCurr.y() - myClickPntZo.y()) * double(getRectPx().height()));
488
+                        if(std::abs(aDx) > myRoot->getClickThreshold()
489
+                        || std::abs(aDy) > myRoot->getClickThreshold()) {
490
+                            myIsClickAborted = true;
491
+                            myClickTimer.stop();
492
+                        }
493
+                    } else {
494
                         myClickTimer.stop();
495
                     }
496
-                } else {
497
-                    myClickTimer.stop();
498
                 }
499
-            }
500
 
501
-            // handle dragging
502
-            if( isClicked(ST_MOUSE_LEFT)
503
-            && !myIsClickAborted
504
-            && !myClickTimer.isOn()) {
505
-                const GLfloat aRectRatio = GLfloat(getRectPx().ratio());
506
-                aParams->moveFlat(getMouseMoveFlat(myClickPntZo, getRoot()->getCursorZo()), aRectRatio);
507
-                if(myDragDelayMs > 1.0) {
508
-                    const GLfloat    aScaleSteps = 0.1f;
509
-                    const StPointD_t aCenterCursor(0.5, 0.5);
510
-                    const StGLVec2   aVec = getMouseMoveFlat(aCenterCursor, getRoot()->getCursorZo()) * (-aScaleSteps);
511
-                    aParams->scaleIn(aScaleSteps);
512
-                    aParams->moveFlat(aVec, aRectRatio);
513
+                // handle dragging
514
+                if(!myIsClickAborted
515
+                && !myClickTimer.isOn()) {
516
+                    // panning
517
+                    const GLfloat aRectRatio = GLfloat(getRectPx().ratio());
518
+                    aParams->moveFlat(getMouseMoveFlat(myClickPntZo, getRoot()->getCursorZo()), aRectRatio);
519
+                    if(aDragDelayMs > 1.0) {
520
+                        const GLfloat    aScaleSteps = 0.1f;
521
+                        const StPointD_t aCenterCursor(0.5, 0.5);
522
+                        const StGLVec2   aVec = getMouseMoveFlat(aCenterCursor, getRoot()->getCursorZo()) * (-aScaleSteps);
523
+                        aParams->scaleIn(aScaleSteps);
524
+                        aParams->moveFlat(aVec, aRectRatio);
525
+                    }
526
+                } else if(!myList.isNull()) {
527
+                    // previous / next swipe gesture
528
+                    const double anIntensMult = toDragImageInSwipe ? 1.0 : 3.0;
529
+                    const StPlayList::CurrentPosition aPos = myList->getCurrentPosition();
530
+                    const double aMouseDX = myClickPntZo.x() - getRoot()->getCursorZo().x();
531
+                    const float aScaleSteps = (float )stMin(std::abs(aMouseDX) * anIntensMult, 1.0);
532
+                    if(aMouseDX < 0.0) {
533
+                        // previous
534
+                        if(aPos == StPlayList::CurrentPosition_Middle
535
+                        || aPos == StPlayList::CurrentPosition_Last) {
536
+                            //params.Brightness->setValue(aBrightnessBack - aScaleSteps);
537
+                            //aParams->scaleIn(-aScaleSteps);
538
+                            if(toDragImageInSwipe) {
539
+                                StGLVec2 aVec = getMouseMoveFlat(myClickPntZo, getRoot()->getCursorZo());
540
+                                aVec.y() = 0.0;
541
+                                aParams->moveFlat(aVec, float(getRectPx().ratio()));
542
+                            }
543
+                            myIconPrev->setOpacity(aScaleSteps, false);
544
+                        }
545
+                    } else {
546
+                        // next
547
+                        if(aPos == StPlayList::CurrentPosition_Middle
548
+                        || aPos == StPlayList::CurrentPosition_First) {
549
+                            if(toDragImageInSwipe) {
550
+                                StGLVec2 aVec = getMouseMoveFlat(myClickPntZo, getRoot()->getCursorZo());
551
+                                aVec.y() = 0.0;
552
+                                aParams->moveFlat(aVec, float(getRectPx().ratio()));
553
+                            }
554
+                            myIconNext->setOpacity(aScaleSteps, false);
555
+                        }
556
+                    }
557
+                }
558
+            } else if(myFadeTimer.isOn()) {
559
+                static const double THE_FADE_ANIM_MS = 1000.0;
560
+                const double aProgress  = myFadeTimer.getElapsedTimeInMilliSec() / THE_FADE_ANIM_MS;
561
+                const double aFadeClamp = stMin(1.0, aProgress);
562
+                const bool isNext = myFadeFrom.x() < myClickPntZo.x();
563
+                if(toDragImageInSwipe) {
564
+                    StPointD_t aFadeTo = myFadeFrom;
565
+                    aFadeTo.x() += isNext ? -aFadeClamp : aFadeClamp;
566
+
567
+                    StGLVec2 aVec = getMouseMoveFlat(myClickPntZo, aFadeTo);
568
+                    aVec.y() = 0.0;
569
+                    aParams->moveFlat(aVec, float(getRectPx().ratio()));
570
                 }
571
+                params.Brightness->setValue(aBrightnessBack - (float )aFadeClamp * 3.0f);
572
+
573
+                // animate icon opacity in loop
574
+                const double anIntensMult  = toDragImageInSwipe ? 1.0 : 3.0;
575
+                const double anOpacityFrom = stMin(std::abs(myClickPntZo.x() - myFadeFrom.x()) * anIntensMult, 1.0);
576
+                double anIconProgress = anOpacityFrom + aProgress;
577
+                const bool isEven = (int(anIconProgress) % 2) == 0;
578
+                anIconProgress -= int(anIconProgress);
579
+                if(!isEven) { anIconProgress = 1.0 - anIconProgress; }
580
+                StGLIcon* anIcon = isNext ? myIconNext : myIconPrev;
581
+                anIcon->setOpacity((float )anIconProgress, false);
582
             }
583
 
584
             GLfloat anXRotate = aParams->getXRotate();
585
@@ -748,6 +1043,7 @@
586
             }
587
 
588
             // apply scale
589
+            const float aVrScale = float(myRoot->getVrZoomOut());
590
             aModelMat.scale(aParams->ScaleFactor * aVrScale, aParams->ScaleFactor * aVrScale, 1.0f);
591
 
592
             // apply position
593
@@ -785,6 +1081,7 @@
594
                              case StFormat_SideBySide_RL: {
595
                                 if(aDispRatio >= 0.85 && aDispRatio <= 1.18) {
596
                                     aDispRatio *= 2.0;
597
+                                    mySampleRatio *= 2.0f;
598
                                 }
599
                                 break;
600
                              }
601
@@ -792,6 +1089,7 @@
602
                              case StFormat_TopBottom_RL: {
603
                                 if(aDispRatio >= 3.5 && aDispRatio <= 4.8) {
604
                                     aDispRatio *= 0.5;
605
+                                    mySampleRatio *= 0.5f;
606
                                 }
607
                                 break;
608
                              }
609
@@ -815,24 +1113,64 @@
610
                 aModelMat.translate(StGLVec3( aSepDeltaX * 0.5f,  aSepDeltaY * 0.5f, 0.0f));
611
             }
612
 
613
-            StGLMatrix anOrthoMat;
614
-            anOrthoMat.initOrtho(StGLVolume(-aRectRatio * aFrustrumL, aRectRatio * aFrustrumR,
615
-                                            -1.0f       * aFrustrumB, 1.0f       * aFrustrumT,
616
-                                            -1.0f, 1.0f));
617
-            myProgram.getActiveProgram()->setProjMat (aCtx, anOrthoMat);
618
-            myProgram.getActiveProgram()->setModelMat(aCtx, aModelMat);
619
+            if(myProgram.init(aCtx, aTextures.getColorModel(), aTextures.getColorScale(), aColorGetter)) {
620
+                myProgram.getActiveProgram()->use(aCtx);
621
 
622
-            myQuad.draw(aCtx, *myProgram.getActiveProgram());
623
+                // setup data rectangle in the texture
624
+                myProgram.setTextureSizePx      (aCtx, aTextureSize);
625
+                myProgram.setTextureMainDataSize(aCtx, aClampVec);
626
+                myProgram.setTextureUVDataSize  (aCtx, aClampUV);
627
+                myProgram.setTextureADataSize   (aCtx, aClampA);
628
 
629
-            myProgram.getActiveProgram()->unuse(aCtx);
630
+                StGLMatrix anOrthoMat;
631
+                anOrthoMat.initOrtho(StGLVolume(-aRectRatio * aFrustrumL, aRectRatio * aFrustrumR,
632
+                                                -1.0f       * aFrustrumB, 1.0f       * aFrustrumT,
633
+                                                -1.0f, 1.0f));
634
+                myProgram.getActiveProgram()->setProjMat (aCtx, anOrthoMat);
635
+                myProgram.getActiveProgram()->setModelMat(aCtx, aModelMat);
636
+
637
+                myQuad.draw(aCtx, *myProgram.getActiveProgram());
638
+
639
+                myProgram.getActiveProgram()->unuse(aCtx);
640
+            }
641
 
642
             // restore changed parameters
643
             aParams->ScaleFactor = aScaleBack;
644
             aParams->PanCenter   = aPanBack;
645
+            params.Brightness->setValue(aBrightnessBack);
646
             break;
647
         }
648
-        case StViewSurface_Cubemap: {
649
-            if(!myProgram.init(aCtx, aTextures.getColorModel(), aTextures.getColorScale(), StGLImageProgram::FragGetColor_Cubemap)) {
650
+        case StViewSurface_Cubemap:
651
+        case StViewSurface_CubemapEAC: {
652
+            // Clamping range is passed through vertex attributes.
653
+            // To avoid extra vertex attributes, the smallest clamping range is used across planes.
654
+            // This trick is possible, because cubemap texture lazy resizing is not used,
655
+            // hence all planes should have same proportions.
656
+            // The result will be broken for rare formats like YUV422P/YUV411P/YUV440P.
657
+            StGLVec4 aClamVecMin = aClampVec;
658
+            if(aTextureUVSize.x() > 0.0f
659
+            && aTextureUVSize.y() > 0.0f) {
660
+                aClamVecMin.x() = stMax(aClamVecMin.x(), aClampUV.x());
661
+                aClamVecMin.y() = stMax(aClamVecMin.y(), aClampUV.y());
662
+                aClamVecMin.z() = stMin(aClamVecMin.z(), aClampUV.z());
663
+                aClamVecMin.w() = stMin(aClamVecMin.w(), aClampUV.w());
664
+            }
665
+            if(aTextureASize.x() > 0.0f
666
+            && aTextureASize.y() > 0.0f) {
667
+                aClamVecMin.x() = stMax(aClamVecMin.x(), aClampA.x());
668
+                aClamVecMin.y() = stMax(aClamVecMin.y(), aClampA.y());
669
+                aClamVecMin.z() = stMin(aClamVecMin.z(), aClampA.z());
670
+                aClamVecMin.w() = stMin(aClamVecMin.w(), aClampA.w());
671
+            }
672
+
673
+            if(myCubeClamp != aClamVecMin
674
+            || myCubePano != aTextures.getPlane().getPackedPanorama()) {
675
+                stglInitCube(aClamVecMin, aTextures.getPlane().getPackedPanorama());
676
+            }
677
+
678
+            if(!myProgram.init(aCtx, aTextures.getColorModel(), aTextures.getColorScale(),
679
+                               StGLImageProgram::FragGetColor_Cubemap,
680
+                               aViewMode == StViewSurface_CubemapEAC ? StGLImageProgram::FragTexEAC_On : StGLImageProgram::FragTexEAC_Off)) {
681
                 break;
682
             }
683
 
684
@@ -842,24 +1180,37 @@
685
             myProgram.setTextureSizePx      (aCtx, aTextureSize);
686
             myProgram.setTextureMainDataSize(aCtx, aClampVec);
687
             myProgram.setTextureUVDataSize  (aCtx, aClampUV);
688
+            myProgram.setTextureADataSize   (aCtx, aClampA);
689
             myProgram.setCubeTextureFlipZ   (aCtx, aParams->ToFlipCubeZ);
690
 
691
-            const float aScale = THE_PANORAMA_DEF_ZOOM * aParams->ScaleFactor * aVrScale;
692
+            const float aScale = aParams->ScaleFactor;
693
             aModelMat.scale(aScale, aScale, 1.0f);
694
 
695
             // compute orientation
696
             const StGLQuaternion anOri = getHeadOrientation(theView, true);
697
             aModelMat = StGLMatrix::multiply(aModelMat, StGLMatrix(anOri));
698
-
699
-            StGLMatrix aMatModelInv, aMatProjInv;
700
-            aModelMat.inverted(aMatModelInv);
701
-            myProjCam.getProjMatrixMono().inverted(aMatProjInv);
702
-            myProgram.getActiveProgram()->setProjMat (aCtx, StGLMatrix::multiply(aMatModelInv, aMatProjInv));
703
             myProgram.getActiveProgram()->setModelMat(aCtx, aModelMat);
704
 
705
-            ///glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
706
+            if(myProjCam.isCustomProjection()) {
707
+                myProgram.getActiveProgram()->setProjMat (aCtx, myProjCam.getProjMatrix());
708
+            } else {
709
+                myProgram.getActiveProgram()->setProjMat (aCtx, myProjCam.getProjMatrixMono());
710
+            }
711
 
712
-            myQuad.draw(aCtx, *myProgram.getActiveProgram());
713
+        #if !defined(GL_ES_VERSION_2_0)
714
+            // Issues with seamless cubemap filtering:
715
+            // - Desktop, available since OpenGL 3.2+ (or ARB_seamless_cube_map) and DISABLED by default;
716
+            //   some old implementations might be buggy;
717
+            //   some very old implementation might even switch to software fallback.
718
+            // - Mobile, OpenGL ES 3.0 requires cubemap filtering to be always ENABLED - no API for disabling;
719
+            //   OpenGL ES 3.0 implementations might not support seamless filtering without a way to detect it.
720
+            // - Seamless filtering works is desired for a proper cubemap definition,
721
+            //   but undesired for EAC video frames with non-square cube sides and has rotated sides.
722
+            if(aCtx.isGlGreaterEqual(3, 2)) {
723
+                ///glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
724
+            }
725
+        #endif
726
+            myCube.draw(aCtx, *myProgram.getActiveProgram());
727
 
728
             myProgram.getActiveProgram()->unuse(aCtx);
729
 
730
@@ -868,13 +1219,46 @@
731
             aParams->PanCenter   = aPanBack;
732
             break;
733
         }
734
+        case StViewSurface_Cylinder:
735
+        case StViewSurface_Theater:
736
+        case StViewSurface_Hemisphere:
737
         case StViewSurface_Sphere: {
738
             if(!myProgram.init(aCtx, aTextures.getColorModel(), aTextures.getColorScale(), aColorGetter)) {
739
                 break;
740
             }
741
 
742
+            StGLMesh* aMesh = &myUVSphere;
743
+            if(aViewMode == StViewSurface_Hemisphere) {
744
+                aMesh = &myHemisphere;
745
+            } else if(aViewMode == StViewSurface_Cylinder) {
746
+                aMesh = &myCylinder;
747
+                const StGLVec2 aSrcSize (aTextures.getPlane().getDataSize().x() * (float )aTextures.getPlane().getSizeX(),
748
+                                         aTextures.getPlane().getDataSize().y() * (float )aTextures.getPlane().getSizeY());
749
+                float aCylHeight = float(2.0 * M_PI * aSrcSize.y()) / aSrcSize.x();
750
+                //aVertScale *= aTextures.getPlane().getDisplayRatio();
751
+                if(myCylinder.getHeight() != aCylHeight) {
752
+                    myCylinder.setHeight(aCylHeight);
753
+                    myCylinder.release(aCtx);
754
+                }
755
+            } else if(aViewMode == StViewSurface_Theater) {
756
+                aMesh = &myTheater;
757
+                const float aCylWidth = float(M_PI * myTheater.getRadius() / myTheater.getAngle());
758
+                const float aCylHeight = (aCylWidth / aTextures.getPlane().getDisplayRatio()) * 0.75f;
759
+                if(myTheater.getHeight() != aCylHeight) {
760
+                    myTheater.setHeight(aCylHeight);
761
+                    myTheater.release(aCtx);
762
+                }
763
+            }
764
+            if(!aMesh->changeVBO(ST_VBO_VERTEX)->isValid()) {
765
+                if(!aMesh->initVBOs(aCtx)) {
766
+                    aCtx.pushError(StString("Fail to init mesh data"));
767
+                    ST_ERROR_LOG("Fail to init mesh data");
768
+                    break;
769
+                }
770
+            }
771
+
772
             // perform scaling
773
-            const float aScale = THE_SPHERE_RADIUS * THE_PANORAMA_DEF_ZOOM * aParams->ScaleFactor * aVrScale;
774
+            const float aScale = THE_SPHERE_RADIUS * aParams->ScaleFactor;
775
             aModelMat.scale(aScale, aScale, THE_SPHERE_RADIUS);
776
 
777
             // compute orientation
778
@@ -888,11 +1272,16 @@
779
             myProgram.setTextureSizePx      (aCtx, aTextureSize);
780
             myProgram.setTextureMainDataSize(aCtx, aClampVec);
781
             myProgram.setTextureUVDataSize  (aCtx, aClampUV);
782
+            myProgram.setTextureADataSize   (aCtx, aClampA);
783
 
784
-            myProgram.getActiveProgram()->setProjMat (aCtx, myProjCam.getProjMatrixMono());
785
             myProgram.getActiveProgram()->setModelMat(aCtx, aModelMat);
786
+            if(myProjCam.isCustomProjection()) {
787
+                myProgram.getActiveProgram()->setProjMat (aCtx, myProjCam.getProjMatrix());
788
+            } else {
789
+                myProgram.getActiveProgram()->setProjMat (aCtx, myProjCam.getProjMatrixMono());
790
+            }
791
 
792
-            myUVSphere.draw(aCtx, *myProgram.getActiveProgram());
793
+            aMesh->draw(aCtx, *myProgram.getActiveProgram());
794
 
795
             myProgram.getActiveProgram()->unuse(aCtx);
796
             break;
797
@@ -933,7 +1322,10 @@
798
 bool StGLImageRegion::tryClick(const StClickEvent& theEvent,
799
                                bool&               theIsItemClicked) {
800
     StHandle<StStereoParams> aParams = getSource();
801
-    if(!myIsInitialized || aParams.isNull()) {
802
+    const bool hasImage = !aParams.isNull()
803
+                        && myHasVideoStream
804
+                        && myTextureQueue->getQTexture().getFront(StGLQuadTexture::LEFT_TEXTURE).isValid();
805
+    if(!myIsInitialized || !hasImage) {
806
         return false;
807
     }
808
 
809
@@ -946,6 +1338,14 @@
810
             myClickPntZo = StPointD_t(theEvent.PointX, theEvent.PointY);
811
             myClickTimer.restart();
812
             myIsClickAborted = false;
813
+
814
+            myDragDelayTmpMs = 0.0f;
815
+            if(aParams->ViewingMode == StViewSurface_Plain
816
+            && fabs(aParams->ScaleFactor - 1.0f) < 0.00001f
817
+            && fabs(aParams->PanCenter.x()) < 0.00001f
818
+            && fabs(aParams->PanCenter.y()) < 0.00001f) {
819
+                myDragDelayTmpMs = 250.0;
820
+            }
821
         }
822
         theIsItemClicked = true;
823
         return true;
824
@@ -956,7 +1356,10 @@
825
 bool StGLImageRegion::tryUnClick(const StClickEvent& theEvent,
826
                                  bool&               theIsItemUnclicked) {
827
     StHandle<StStereoParams> aParams = getSource();
828
-    if(!myIsInitialized || aParams.isNull()) {
829
+    const bool hasImage = !aParams.isNull()
830
+                        && myHasVideoStream
831
+                        && myTextureQueue->getQTexture().getFront(StGLQuadTexture::LEFT_TEXTURE).isValid();
832
+    if(!myIsInitialized || !hasImage) {
833
         if(isClicked(theEvent.Button)) {
834
             theIsItemUnclicked = true;
835
             setClicked(theEvent.Button, false);
836
@@ -976,10 +1379,39 @@
837
             case StViewSurface_Plain: {
838
                 if(!myIsClickAborted) {
839
                     aParams->moveFlat(getMouseMoveFlat(myClickPntZo, aCursor), GLfloat(getRectPx().ratio()));
840
+                } else if(!myList.isNull()) {
841
+                    // previous / next swipe gesture
842
+                    StPlayList::CurrentPosition aPos = myList->getCurrentPosition();
843
+                    const double aMouseDX = myClickPntZo.x() - getRoot()->getCursorZo().x();
844
+                    if(std::abs(aMouseDX) >= 0.25) {
845
+                        if(aMouseDX < 0.0) {
846
+                            if(aPos == StPlayList::CurrentPosition_Middle
847
+                            || aPos == StPlayList::CurrentPosition_Last) {
848
+                                if(myList->walkToPrev()) {
849
+                                    signals.onOpenItem();
850
+                                    myFadeTimer.restart();
851
+                                    myFadeFrom = getRoot()->getCursorZo();
852
+                                }
853
+                            }
854
+                        } else {
855
+                            if(aPos == StPlayList::CurrentPosition_Middle
856
+                            || aPos == StPlayList::CurrentPosition_First) {
857
+                                if(myList->walkToNext()) {
858
+                                    signals.onOpenItem();
859
+                                    myFadeTimer.restart();
860
+                                    myFadeFrom = getRoot()->getCursorZo();
861
+                                }
862
+                            }
863
+                        }
864
+                    }
865
                 }
866
                 break;
867
             }
868
             case StViewSurface_Cubemap:
869
+            case StViewSurface_CubemapEAC:
870
+            case StViewSurface_Cylinder:
871
+            case StViewSurface_Theater:
872
+            case StViewSurface_Hemisphere:
873
             case StViewSurface_Sphere: {
874
                 aParams->moveSphere(getMouseMoveSphere(myClickPntZo, aCursor));
875
                 break;
876
@@ -1001,34 +1433,32 @@
877
         return false;
878
     }
879
 
880
-    const GLfloat SCALE_STEPS = fabs(theEvent.DeltaY) * 0.01f;
881
-    if(theEvent.DeltaY > 0.001f) {
882
-        if((myKeyFlags & ST_VF_CONTROL) == ST_VF_CONTROL) {
883
-            if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
884
+    if((myKeyFlags & ST_VF_CONTROL) == ST_VF_CONTROL) {
885
+        if(theEvent.StepsY == 0) {
886
+            return false;
887
+        }
888
+        if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
889
+            if(theEvent.StepsY > 0) {
890
                 doParamsSepZDec(0.01);
891
             } else {
892
-                doParamsSepX(size_t(-1));
893
-            }
894
-            return true;
895
-        } else if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
896
-            doParamsSepY(size_t(-1));
897
-            return true;
898
-        }
899
-
900
-        scaleAt(aCursor, SCALE_STEPS);
901
-    } else if(theEvent.DeltaY < -0.001f) {
902
-        if((myKeyFlags & ST_VF_CONTROL) == ST_VF_CONTROL) {
903
-            if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
904
                 doParamsSepZInc(0.01);
905
-            } else {
906
-                doParamsSepX(size_t(1));
907
             }
908
-            return true;
909
-        } else if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
910
-            doParamsSepY(size_t(1));
911
-            return true;
912
+        } else {
913
+            doParamsSepX(theEvent.StepsY > 0 ? size_t(-1) : size_t(1));
914
+        }
915
+        return true;
916
+    } else if((myKeyFlags & ST_VF_SHIFT) == ST_VF_SHIFT) {
917
+        if(theEvent.StepsY == 0) {
918
+            return false;
919
         }
920
+        doParamsSepY(theEvent.StepsY > 0 ? size_t(-1) : size_t(1));
921
+        return true;
922
+    }
923
 
924
+    const GLfloat SCALE_STEPS = fabs(theEvent.DeltaY) * 0.1f;
925
+    if(theEvent.DeltaY > 0.0001f) {
926
+        scaleAt(aCursor, SCALE_STEPS);
927
+    } else if(theEvent.DeltaY < -0.0001f) {
928
         scaleAt(aCursor, -SCALE_STEPS);
929
     }
930
     return true;
931
@@ -1060,6 +1490,10 @@
932
             break;
933
         }
934
         case StViewSurface_Cubemap:
935
+        case StViewSurface_CubemapEAC:
936
+        case StViewSurface_Cylinder:
937
+        case StViewSurface_Theater:
938
+        case StViewSurface_Hemisphere:
939
         case StViewSurface_Sphere: {
940
             if(theStep < 0.0f
941
             && aParams->ScaleFactor <= 0.24f) {
942
sview-17_04.tar.gz/StGLWidgets/StGLMessageBox.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLMessageBox.cpp Changed
68
 
1
@@ -92,14 +92,15 @@
2
 
3
 void StGLMessageBox::create(const StString& theTitle,
4
                             const StString& theText,
5
-                            const int       theWidth,
6
-                            const int       theHeight) {
7
+                            const int  theWidth,
8
+                            const int  theHeight,
9
+                            const bool theHasButtons) {
10
     StGLWidget::signals.onMouseUnclick.connect(this, &StGLMessageBox::doMouseUnclick);
11
 
12
     myMarginLeft   = myRoot->scale(OFFSET_PIXELS);
13
     myMarginRight  = myRoot->scale(OFFSET_PIXELS);
14
     myMarginTop    = myRoot->scale(OFFSET_PIXELS);
15
-    myMarginBottom = myRoot->scale(24 * 3);
16
+    myMarginBottom = myRoot->scale(theHasButtons ? (24 * 3) : OFFSET_PIXELS);
17
     myMinSizeY     = myRoot->scale(200);
18
 
19
     int aTitleOffset =  myRoot->scale(24);
20
@@ -110,7 +111,7 @@
21
         myMarginLeft   =  myRoot->scale(4);
22
         myMarginRight  =  myRoot->scale(4);
23
         myMarginTop    =  myRoot->scale(4);
24
-        myMarginBottom =  myRoot->scale(32);
25
+        myMarginBottom =  myRoot->scale(theHasButtons ? 32 : 4);
26
         aTitleOffset   =  myRoot->scale(4);
27
         aBtnBot        = -myRoot->scale(4);
28
     }
29
@@ -329,7 +330,7 @@
30
             if(double(aSizeYToFit) / double(aMaxSizeY) > 0.7) {
31
                 aNewSizeY = stMax(myMinSizeY, aMaxSizeY);
32
             }
33
-            changeRectPx().bottom() = aNewSizeY;
34
+            changeRectPx().bottom() = getRectPx().top() + aNewSizeY;
35
             myContent->changeRectPx().bottom() = myContent->getRectPx().top() + aNewSizeY - myMarginTop - myMarginBottom;
36
         }
37
     }
38
@@ -369,7 +370,7 @@
39
     }
40
 
41
     StGLBoxPx aScissorRect;
42
-    stglScissorRect(aScissorRect);
43
+    stglScissorRect2d(aScissorRect);
44
     aCtx.stglSetScissorRect(aScissorRect, true);
45
 
46
     StGLWidget::stglDraw(theView); // draw children
47
@@ -389,17 +390,18 @@
48
 
49
 bool StGLMessageBox::tryUnClick(const StClickEvent& theEvent,
50
                                 bool&               theIsItemUnclicked) {
51
+    const bool wasDragged = myContent->hasDragged();
52
     if(//isPointIn(StPointD_t(theEvent.PointX, theEvent.PointY)) &&
53
        StGLWidget::tryUnClick(theEvent, theIsItemUnclicked)) {
54
         theIsItemUnclicked = true;
55
 
56
-        if(myIsContextual) {
57
+        if(myIsContextual && !wasDragged) {
58
             myRoot->destroyWithDelay(this);
59
         }
60
         return true;
61
     }
62
 
63
-    if(myIsContextual) {
64
+    if(myIsContextual && !wasDragged) {
65
         myRoot->destroyWithDelay(this);
66
     }
67
     return false;
68
sview-17_04.tar.gz/StGLWidgets/StGLOpenFile.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLOpenFile.cpp Changed
507
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2015-2019 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -11,17 +11,250 @@
10
 
11
 #include <StGLWidgets/StGLMenu.h>
12
 #include <StGLWidgets/StGLMenuItem.h>
13
+#include <StGLWidgets/StGLMenuCheckbox.h>
14
+#include <StGLWidgets/StGLCheckbox.h>
15
 #include <StGLWidgets/StGLScrollArea.h>
16
 #include <StGLWidgets/StGLTextureButton.h>
17
 
18
+#include <StThreads/StThread.h>
19
+
20
+#include <fstream>
21
+
22
+#if !defined(_WIN32)
23
+    #include <unistd.h>
24
+#endif
25
+
26
+#ifdef _WIN32
27
+/**
28
+ * Auxiliary tool resolving drive labels.
29
+ */
30
+struct StDriveNameResolver {
31
+
32
+    StMutex Mutex;
33
+    std::vector<StString> Drives;
34
+    std::vector<StString> Labels;
35
+    volatile int NbProcessed;
36
+    volatile bool ToAbort;
37
+
38
+public:
39
+    /**
40
+     * Empty constructor.
41
+     */
42
+    StDriveNameResolver() : NbProcessed(0), ToAbort(false) {}
43
+
44
+    /**
45
+     * Init list.
46
+     */
47
+    void init() {
48
+        const DWORD aLogicalDrivesMask = ::GetLogicalDrives();
49
+        for(int aLetterIter = 'A'; aLetterIter <= 'Z'; ++aLetterIter) {
50
+            const int aBit = 1 << (aLetterIter - 'A');
51
+            if((aLogicalDrivesMask & aBit) != 0) {
52
+                Drives.push_back(StString()         + char(aLetterIter) + ":\\");
53
+                Labels.push_back(StString("Drive ") + char(aLetterIter) + ":\\");
54
+            }
55
+        }
56
+
57
+        // enumerate all physical drives seen by Windows
58
+        const GUID PARTITION_BASIC_DATA_GUID = { 0xEBD0A0A2L, 0xB9E5, 0x4433, {0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7} };
59
+        static const DWORD aPartInfoSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 128 * sizeof(PARTITION_INFORMATION_EX); // up to 128 partitions
60
+        char aPartInfoBuffer[aPartInfoSize] = {};
61
+        DRIVE_LAYOUT_INFORMATION_EX* aPartitions = (DRIVE_LAYOUT_INFORMATION_EX* )aPartInfoBuffer;
62
+        for(int aDriveIter = 0; aDriveIter < 1000; ++aDriveIter) {
63
+            const StStringUtfWide aDriveId = StStringUtfWide(L"\\\\.\\PhysicalDrive") + aDriveIter;
64
+            HANDLE aDriveHandle = CreateFileW(aDriveId.toCString(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
65
+            if(aDriveHandle == INVALID_HANDLE_VALUE) {
66
+                break;
67
+            }
68
+
69
+            // list partitions
70
+            DWORD aDummyIor = 0;
71
+            if(!DeviceIoControl(aDriveHandle, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, aPartitions, aPartInfoSize, &aDummyIor, NULL)) {
72
+                CloseHandle(aDriveHandle);
73
+                continue;
74
+            }
75
+
76
+            for(DWORD aPartIter = 0; aPartIter < aPartitions->PartitionCount; ++aPartIter) {
77
+                const PARTITION_INFORMATION_EX& aPart = aPartitions->PartitionEntry[aPartIter];
78
+                switch(aPart.PartitionStyle) {
79
+                    case PARTITION_STYLE_MBR: {
80
+                        if(aPart.Mbr.PartitionType == PARTITION_ENTRY_UNUSED || !aPart.Mbr.RecognizedPartition) {
81
+                            continue; // ignore unused
82
+                        }
83
+                        break;
84
+                    }
85
+                    case PARTITION_STYLE_GPT: {
86
+                        if(aPart.Gpt.PartitionType != PARTITION_BASIC_DATA_GUID) {
87
+                            continue; // ignore unused
88
+                        }
89
+                        break;
90
+                    }
91
+                    default: {
92
+                        continue; // ignore unknown
93
+                    }
94
+                }
95
+
96
+                const StStringUtfWide aPartVolume = findPartitionVolume(aDriveIter, aPart);
97
+                if(aPartVolume.isEmpty()) {
98
+                    continue;
99
+                }
100
+
101
+                // find mount points
102
+                DWORD aMntPointLen = 0;
103
+                std::vector<wchar_t> aMntPoints(1);
104
+                GetVolumePathNamesForVolumeNameW(aPartVolume.toCString(), aMntPoints.data(), 0, &aMntPointLen);
105
+                if(aMntPointLen > 0) {
106
+                    aMntPoints.resize (aMntPointLen + 1, '\0');
107
+                    if(GetVolumePathNamesForVolumeNameW(aPartVolume.toCString(), aMntPoints.data(), aMntPointLen, &aMntPointLen) != FALSE) {
108
+                        StString aMntPointRes(aMntPoints.data());
109
+                        for(const wchar_t* aMntPointIter = aMntPoints.data(); aMntPointIter[0] != '\0'; aMntPointIter += wcslen(aMntPointIter)) {
110
+                            const StString aMntPoint(aMntPointIter);
111
+                            if(aMntPoint.getLength() == 3
112
+                            && aMntPoint.toCString()[1] == ':'
113
+                            && aMntPoint.toCString()[2] == '\\') {
114
+                                // filter common logical drive letter
115
+                                aMntPointRes.clear();
116
+                                break;
117
+                            }
118
+                        }
119
+                        if(!aMntPointRes.isEmpty()) {
120
+                            if(aMntPointRes.getLength() > 3
121
+                            && aMntPointRes.isEndsWith('\\')) {
122
+                                aMntPointRes = aMntPointRes.subString(0, aMntPointRes.getLength() - 1);
123
+                            }
124
+                            Drives.push_back(aMntPointRes);
125
+                            Labels.push_back(StString("Drive ") + aMntPointRes);
126
+                        }
127
+                    }
128
+                }
129
+            }
130
+            CloseHandle(aDriveHandle);
131
+        }
132
+    }
133
+
134
+    /**
135
+     * Working thread callback.
136
+     */
137
+    void resolve() {
138
+        wchar_t aVolumeName[256];
139
+        wchar_t aFileSystemName[256];
140
+        StString aDriveLabel;
141
+        const StString aDriveA = "A:";
142
+        const StString aDriveB = "B:";
143
+        for(; NbProcessed < (int )Drives.size(); StAtomicOp::Increment(NbProcessed)) {
144
+            const StString& aDrivePath = Drives[NbProcessed];
145
+            StStringUtfWide aDrivePathW = aDrivePath.toUtfWide();
146
+            if(!aDrivePath.isEndsWith('\\')) {
147
+                aDrivePathW += '\\';
148
+            }
149
+            DWORD aSerialNumber = 0, aMaxFileNameLength = 0, aFileSystemFlags = 0;
150
+            if(!aDrivePath.isStartsWithIgnoreCase(aDriveA)
151
+            && !aDrivePath.isStartsWithIgnoreCase(aDriveB)
152
+            && ::GetVolumeInformationW(aDrivePathW.toCString(),
153
+                                       aVolumeName, sizeof(aVolumeName) / sizeof(wchar_t),
154
+                                       &aSerialNumber, &aMaxFileNameLength, &aFileSystemFlags,
155
+                                       aFileSystemName, sizeof(aFileSystemName) / sizeof(wchar_t))) {
156
+                aDriveLabel.fromUnicode(aVolumeName);
157
+                if(!aDriveLabel.isEmpty() && !ToAbort) {
158
+                    StMutexAuto aLock(Mutex);
159
+                    Labels[NbProcessed] = aDrivePath + " [" + aDriveLabel + "]";
160
+                }
161
+            }
162
+
163
+            if(ToAbort) {
164
+                return;
165
+            }
166
+        }
167
+    }
168
+
169
+    /**
170
+     * Working thread callback.
171
+     */
172
+    static SV_THREAD_FUNCTION resolveThread(void* thePtr) {
173
+        StHandle<StDriveNameResolver> aThis = *static_cast<StHandle<StDriveNameResolver>* >(thePtr);
174
+        aThis->resolve();
175
+        return SV_THREAD_RETURN 0;
176
+    }
177
+
178
+        private:
179
+
180
+    /**
181
+     * Find volume name for partition.
182
+     */
183
+    static StStringUtfWide findPartitionVolume(DWORD theDiskNumber, const PARTITION_INFORMATION_EX& thePart) {
184
+        // handle up-to 256 extents
185
+        static const DWORD THE_EXTENTS_SIZE = sizeof(VOLUME_DISK_EXTENTS) + 256 * sizeof(DISK_EXTENT);
186
+        char aBuffer[THE_EXTENTS_SIZE] = {};
187
+        VOLUME_DISK_EXTENTS* aVolDiskExtents = (VOLUME_DISK_EXTENTS* )aBuffer;
188
+
189
+        std::vector<wchar_t> aVolName(4096, '\0');
190
+        HANDLE aVolIter = FindFirstVolumeW(aVolName.data(), (DWORD )aVolName.size());
191
+        for(bool hasMoreVolumes = aVolIter != INVALID_HANDLE_VALUE; hasMoreVolumes; hasMoreVolumes = FindNextVolumeW (aVolIter, aVolName.data(), (DWORD )aVolName.size()) != FALSE) {
192
+            aVolName[wcslen(aVolName.data()) - 1] = '\0'; // volume must be without trailing backslash here
193
+            HANDLE aVolHandle = CreateFileW(aVolName.data(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
194
+            aVolName[wcslen(aVolName.data())] = '\\';
195
+            if(aVolHandle == INVALID_HANDLE_VALUE) {
196
+                continue;
197
+            }
198
+
199
+            DWORD anExtentsSize = 0;
200
+            if(DeviceIoControl(aVolHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, (void* )aVolDiskExtents, THE_EXTENTS_SIZE, &anExtentsSize, NULL) == FALSE) {
201
+                CloseHandle(aVolHandle);
202
+                continue;
203
+            }
204
+
205
+            for(DWORD anExtentIter = 0; anExtentIter < aVolDiskExtents->NumberOfDiskExtents; ++anExtentIter) {
206
+                const DISK_EXTENT& anExtent = aVolDiskExtents->Extents[anExtentIter];
207
+                if(anExtent.DiskNumber == theDiskNumber
208
+                && anExtent.StartingOffset.QuadPart == thePart.StartingOffset.QuadPart
209
+                && anExtent.ExtentLength.QuadPart == thePart.PartitionLength.QuadPart) {
210
+                    CloseHandle(aVolHandle);
211
+                    FindVolumeClose(aVolIter);
212
+                    return StStringUtfWide(aVolName.data());
213
+                }
214
+            }
215
+            CloseHandle(aVolHandle);
216
+        }
217
+        FindVolumeClose(aVolIter);
218
+        return StStringUtfWide();
219
+    }
220
+
221
+};
222
+#endif
223
+
224
+/**
225
+ * Dummy sub-class overriding scrollable behavior.
226
+ */
227
+class StGLOpenFileMenu : public StGLMenu {
228
+
229
+        public:
230
+
231
+    ST_LOCAL StGLOpenFileMenu(StGLWidget* theParent,
232
+                              int  theLeft,
233
+                              int  theTop,
234
+                              int  theOrient = MENU_VERTICAL,
235
+                              bool theIsRootMenu = false)
236
+    : StGLMenu(theParent, theLeft, theTop, theOrient, theIsRootMenu) {}
237
+
238
+    ST_LOCAL virtual bool doScroll(const StScrollEvent& theEvent) ST_ATTR_OVERRIDE {
239
+        return StGLWidget::doScroll(theEvent); // skip StGLMenu
240
+    }
241
+
242
+};
243
+
244
 StGLOpenFile::StGLOpenFile(StGLWidget*     theParent,
245
                            const StString& theTitle,
246
                            const StString& theCloseText)
247
 : StGLMessageBox(theParent, theTitle, "",
248
                  theParent->getRoot()->scale(512), theParent->getRoot()->scale(400)),
249
   myCurrentPath(NULL),
250
+  myHotListContent(NULL),
251
   myHotList(NULL),
252
   myList(NULL),
253
+  myMainFilterCheck(NULL),
254
+  myExtraFilterCheck(NULL),
255
+  myToShowMainFilter(new StBoolParam(true)),
256
+  myToShowExtraFilter(new StBoolParam(false)),
257
   myHighlightColor(0.5f, 0.5f, 0.5f, 1.0f),
258
   myItemColor     (1.0f, 1.0f, 1.0f, 1.0f),
259
   myFileColor     (0.7f, 0.7f, 0.7f, 1.0f),
260
@@ -31,6 +264,9 @@
261
   myIconSizeX(theParent->getRoot()->scale(16)) {
262
     myToAdjustY = false;
263
 
264
+    myToShowMainFilter ->signals.onChanged = stSlot(this, &StGLOpenFile::doFilterCheck);
265
+    myToShowExtraFilter->signals.onChanged = stSlot(this, &StGLOpenFile::doFilterCheck);
266
+
267
     int aMarginTop = myMarginTop + myRoot->scale(30);
268
     myCurrentPath = new StGLTextArea(this, myMarginLeft, myMarginTop, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
269
                                      myContent->getRectPx().width(), myContent->getRectPx().height());
270
@@ -38,17 +274,19 @@
271
                                   StGLTextFormatter::ST_ALIGN_Y_TOP);
272
     myCurrentPath->setTextColor(myRoot->getColorForElement(StGLRootWidget::Color_MessageText));
273
 
274
-    myHotList = new StGLMenu(this, 0, 0, StGLMenu::MENU_VERTICAL_COMPACT);
275
+    myContent->changeRectPx().top()  = aMarginTop;
276
+    myContent->changeRectPx().left() = myMarginLeft + myHotSizeX;
277
+
278
+    myHotListContent = new StGLScrollArea(this, myMarginLeft, aMarginTop,
279
+                                          StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
280
+                                          myHotSizeX, myContent->getRectPx().height());
281
+
282
+    myHotList = new StGLOpenFileMenu(myHotListContent, 0, 0, StGLMenu::MENU_VERTICAL_COMPACT);
283
     myHotList->setOpacity(1.0f, true);
284
     myHotList->setItemWidth(myHotSizeX);
285
     myHotList->setColor(StGLVec4(0.0f, 0.0f, 0.0f, 0.0f));
286
-    myHotList->changeRectPx().top()   = aMarginTop;
287
-    myHotList->changeRectPx().left()  = myMarginLeft;
288
-    myHotList->changeRectPx().right() = myMarginLeft + myHotSizeX;
289
-    myContent->changeRectPx().top()   = aMarginTop;
290
-    myContent->changeRectPx().left()  = myMarginLeft + myHotSizeX;
291
 
292
-    myList = new StGLMenu(myContent, 0, 0, StGLMenu::MENU_VERTICAL_COMPACT);
293
+    myList = new StGLOpenFileMenu(myContent, 0, 0, StGLMenu::MENU_VERTICAL_COMPACT);
294
     myList->setOpacity(1.0f, true);
295
     myList->setColor(StGLVec4(0.0f, 0.0f, 0.0f, 0.0f));
296
     myList->setItemWidthMin(myContent->getRectPx().width());
297
@@ -56,6 +294,88 @@
298
     //if(!myRoot->isMobile()) {
299
         addButton(theCloseText);
300
     //}
301
+
302
+    addSystemDrives();
303
+}
304
+
305
+void StGLOpenFile::addSystemDrives() {
306
+#ifdef _WIN32
307
+    StHandle<StDriveNameResolver> aResolver = new StDriveNameResolver();
308
+    aResolver->init();
309
+    if(!aResolver->Drives.empty()) {
310
+        // name resolver might hang on resource unavailability
311
+        StThread aThread(StDriveNameResolver::resolveThread, &aResolver);
312
+        if(!aThread.wait(1000)) {
313
+            //aThread.kill();
314
+            aResolver->ToAbort = true;
315
+            aThread.detach();
316
+        }
317
+
318
+        StMutexAuto aLock(aResolver->Mutex);
319
+        for(size_t aDriveIter = 0; aDriveIter < aResolver->Drives.size(); ++aDriveIter) {
320
+            addHotItem(aResolver->Drives[aDriveIter], aResolver->Labels[aDriveIter]);
321
+        }
322
+    }
323
+#else
324
+    // modern Android does not permit listing / content
325
+    if(access("/", R_OK) == 0) {
326
+        addHotItem("/", "Root");
327
+    }
328
+#endif
329
+
330
+#if defined(__ANDROID__)
331
+    std::ifstream aMountsFile("/proc/mounts");
332
+    if(!aMountsFile.is_open()) {
333
+        return;
334
+    }
335
+    std::string aLineStd;
336
+    while(std::getline(aMountsFile, aLineStd)) {
337
+        const StString aLine(aLineStd.c_str());
338
+        StHandle<StArrayList<StString> > aMountLine = aLine.split(' ');
339
+        if(aMountLine->size() < 4) {
340
+            continue;
341
+        }
342
+
343
+        const StString& aDevice  = aMountLine->getValue(0);
344
+        const StString& aMount   = aMountLine->getValue(1);
345
+        const StString& aFileSys = aMountLine->getValue(2);
346
+        const StString aMountLower = aMount.lowerCased();
347
+        // filter by unsupported file-system
348
+        /*if(aFileSys == stCString("tmpfs")
349
+        || aFileSys == stCString("devpts")
350
+        || aFileSys == stCString("sysfs")
351
+        || aFileSys == stCString("selinuxfs")
352
+        || aFileSys == stCString("debugfs")
353
+        || aFileSys == stCString("configfs")
354
+        || aFileSys == stCString("cgroup")
355
+        || aFileSys == stCString("functionfs")) {
356
+            continue;
357
+        }*/
358
+        // filter by supported file-system
359
+        if(aFileSys != stCString("fuse")
360
+        && aFileSys != stCString("vfat")
361
+        && aFileSys != stCString("ntfs")
362
+        && aFileSys != stCString("ext4")) {
363
+            continue;
364
+        }
365
+        // filter special paths
366
+        if(aMountLower.isStartsWith(stCString("/mnt/secure"))
367
+        || aMountLower.isStartsWith(stCString("/mnt/asec"))
368
+        || aMountLower.isStartsWith(stCString("/mnt/mapper"))
369
+        || aMountLower.isStartsWith(stCString("/mnt/obb"))
370
+        || aMountLower == stCString("/storage/emulated")
371
+        || aMountLower.isStartsWith(stCString("/mnt/shell/emulated"))         // ignore symlink to /storage/emulated/0/ for current user, Android 4.2+
372
+        || aMountLower.isStartsWith(stCString("/storage/emulated/legacy"))) { // ignore symlink to /storage/emulated/X/ for current user
373
+            continue;
374
+        }
375
+        // filter bootdevice entities
376
+        if( aDevice.isStartsWith(stCString("/dev/block"))
377
+        && !aDevice.isStartsWith(stCString("/dev/block/vold"))) {
378
+            continue;
379
+        }
380
+        addHotItem(aMount);
381
+    }
382
+#endif
383
 }
384
 
385
 StGLOpenFile::~StGLOpenFile() {
386
@@ -74,15 +394,70 @@
387
     }
388
 }
389
 
390
-void StGLOpenFile::setMimeList(const StMIMEList& theFilter) {
391
-    myFilter     = theFilter;
392
-    myExtensions = theFilter.getExtensionsList();
393
+void StGLOpenFile::setMimeList(const StMIMEList& theFilter,
394
+                               const StString& theName,
395
+                               const bool theIsExtra) {
396
+    if(theIsExtra) {
397
+        myExtraFilter = theFilter;
398
+    } else {
399
+        myFilter = theFilter;
400
+    }
401
+
402
+    StGLMenuCheckbox*& aFilterWidget = theIsExtra ? myExtraFilterCheck : myMainFilterCheck;
403
+    if(!theName.isEmpty() && aFilterWidget == NULL) {
404
+        StHandle<StBoolParam>& aFilterParam = theIsExtra ? myToShowExtraFilter : myToShowMainFilter;
405
+        aFilterWidget = addHotCheckbox(aFilterParam, theName);
406
+    }
407
+    if(aFilterWidget != NULL) {
408
+        aFilterWidget->setText(theName);
409
+    }
410
+    initExtensions();
411
+}
412
+
413
+StGLMenuCheckbox* StGLOpenFile::addHotCheckbox(const StHandle<StBoolParam>& theParam,
414
+                                               const StString& theName) {
415
+    StGLMenuCheckbox* aFilterWidget = new StGLMenuCheckbox(myHotList, theParam);
416
+
417
+    StGLCheckbox* aCheckBox = aFilterWidget->getCheckbox();
418
+    aCheckBox->setColor(myHotColor);
419
+    aCheckBox->setCorner(StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
420
+    aCheckBox->changeRectPx().moveLeftTo(-aCheckBox->getRectPx().left());
421
+
422
+    aFilterWidget->changeMargins().left  = -(myMarginX + myIconSizeX + myMarginX); // TODO weird logic
423
+    aFilterWidget->setupStyle(StFTFont::Style_Italic);
424
+    aFilterWidget->setText(theName);
425
+    aFilterWidget->setupAlignment(StGLTextFormatter::ST_ALIGN_X_RIGHT, StGLTextFormatter::ST_ALIGN_Y_CENTER);
426
+    aFilterWidget->setTextColor(myHotColor);
427
+    aFilterWidget->setHilightColor(myHighlightColor);
428
+    return aFilterWidget;
429
+}
430
+
431
+void StGLOpenFile::initExtensions() {
432
+    myExtensions.clear();
433
+    StArrayList<StString> aList1 = myToShowMainFilter ->getValue() ? myFilter.getExtensionsList()      : StArrayList<StString>(1);
434
+    StArrayList<StString> aList2 = myToShowExtraFilter->getValue() ? myExtraFilter.getExtensionsList() : StArrayList<StString>(1);
435
+    size_t anExtent = aList1.size() + aList2.size();
436
+    myExtensions.initList(anExtent);
437
+    for(size_t anExtIter = 0; anExtIter < aList1.size(); ++anExtIter) {
438
+        myExtensions.add(aList1[anExtIter]);
439
+    }
440
+    for(size_t anExtIter = 0; anExtIter < aList2.size(); ++anExtIter) {
441
+        myExtensions.add(aList2[anExtIter]);
442
+    }
443
 }
444
 
445
 void StGLOpenFile::doHotItemClick(const size_t theItemId) {
446
     myItemToLoad = myHotPaths[theItemId];
447
 }
448
 
449
+void StGLOpenFile::doFilterCheck(const bool ) {
450
+    initExtensions();
451
+    if(!myFolder.isNull()) {
452
+        StString aPath = myFolder->getPath();
453
+        openFolder(aPath);
454
+    }
455
+}
456
+
457
 void StGLOpenFile::doFileItemClick(const size_t theItemId) {
458
     const StFileNode* aNode = myFolder->getValue(theItemId);
459
     myItemToLoad = aNode->getPath();
460
@@ -104,10 +479,14 @@
461
         myItemToLoad.clear();
462
         if(StFolder::isFolder(aPath)) {
463
             openFolder(aPath);
464
-        } else {
465
+        } else if(StFileNode::isFileExists(aPath)) {
466
             StHandle<StString> aPathHandle = new StString(aPath);
467
             signals.onFileSelected.emit(aPathHandle);
468
             myRoot->destroyWithDelay(this);
469
+        } else {
470
+            StGLMessageBox* aMsgBox = new StGLMessageBox(myRoot, "Error", StString("Path is inaccessible!\n") + aPath);
471
+            aMsgBox->addButton("Close");
472
+            aMsgBox->stglInit();
473
         }
474
     }
475
     return aRes;
476
@@ -132,6 +511,7 @@
477
 
478
     StGLMenuItem* anItem = new StGLPassiveMenuItem(myHotList);
479
     setItemIcon(anItem, myHotColor, true);
480
+    anItem->setupStyle(StFTFont::Style_Bold);
481
     anItem->setText(aName);
482
     anItem->setTextColor(myHotColor);
483
     anItem->setHilightColor(myHighlightColor);
484
@@ -141,7 +521,11 @@
485
     int aSizeX = anItem->getMargins().left + anItem->computeTextWidth() + anItem->getMargins().right;
486
     myHotSizeX = stMax(myHotSizeX, aSizeX);
487
 
488
-    myContent->changeRectPx().left() = myMarginLeft + myHotSizeX;
489
+    myHotListContent->changeRectPx().right() = myHotListContent->getRectPx().left() + myHotSizeX;
490
+    if(myMainFilterCheck != NULL) {
491
+        myMainFilterCheck->changeRectPx().right() = myHotSizeX;
492
+    }
493
+    myContent->changeRectPx().left() = myHotListContent->getRectPx().right();
494
     myList->setItemWidthMin(myContent->getRectPx().width());
495
 }
496
 
497
@@ -193,7 +577,8 @@
498
     myFolder = new StFolder(aFolder);
499
     myFolder->init(myExtensions, 1, true);
500
     StString aPath = myFolder->getPath();
501
-    myCurrentPath->setText(StString("<b>Location:*</b>") + aPath + (!aPath.isEmpty() ? ST_FILE_SPLITTER : ""));
502
+    myCurrentPath->setText(StString("<b>Location:*</b>") + aPath
503
+                         + (!aPath.isEmpty() && !aPath.isEndsWith(SYS_FS_SPLITTER) ? ST_FILE_SPLITTER : ""));
504
 
505
     StString aPathUp = StFileNode::getFolderUp(aPath);
506
     if(!aPathUp.isEmpty()) {
507
sview-17_04.tar.gz/StGLWidgets/StGLPlayList.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLPlayList.cpp Changed
10
 
1
@@ -376,7 +376,7 @@
2
 
3
     StGLContext& aCtx = getContext();
4
     StGLBoxPx aScissorRect;
5
-    stglScissorRect(aScissorRect);
6
+    stglScissorRect2d(aScissorRect);
7
     aCtx.stglSetScissorRect(aScissorRect, true);
8
 
9
     StGLWidget::stglDraw(theView);
10
sview-17_04.tar.gz/StGLWidgets/StGLRootWidget.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLRootWidget.cpp Changed
101
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -263,31 +263,27 @@
10
     myGlCtx->stglSyncState();
11
     myGlCtx->core20fwd->glGetIntegerv(GL_VIEWPORT, myViewport); // cache viewport
12
 
13
-    switch(theView) {
14
-        case ST_DRAW_LEFT:
15
-            myScrDispX   =             myLensDist * GLfloat(0.5 * myRectGl.width());
16
-            myScrDispXPx =  int(double(myLensDist) * 0.5 * double(myRectPxFull.width()));
17
-            break;
18
-        case ST_DRAW_RIGHT:
19
-            myScrDispX   =            -myLensDist * GLfloat(0.5 * myRectGl.width());
20
-            myScrDispXPx = -int(double(myLensDist) * 0.5 * double(myRectPxFull.width()));
21
-            break;
22
-        case ST_DRAW_MONO:
23
-        default:
24
-            myScrDispX   = 0.0f;
25
-            myScrDispXPx = 0;
26
-            break;
27
-    }
28
-
29
-    if(myTextProgram->isValid()) {
30
-        myTextProgram->use(*myGlCtx);
31
-        myTextProgram->setProjMat(*myGlCtx,       myProjCamera.getProjMatrix());
32
-        myTextProgram->unuse(*myGlCtx);
33
-    }
34
-    if(myTextBorderProgram->isValid()) {
35
-        myTextBorderProgram->use(*myGlCtx);
36
-        myTextBorderProgram->setProjMat(*myGlCtx, myProjCamera.getProjMatrix());
37
-        myTextBorderProgram->unuse(*myGlCtx);
38
+    myScrDispX   = 0.0f;
39
+    myScrDispXPx = 0;
40
+    if(theView == ST_DRAW_LEFT || theView == ST_DRAW_RIGHT) {
41
+        if(myProjCamera.isCustomProjection()) {
42
+            StGLVec4 aTestProj = myProjCamera.getProjMatrix() * StGLVec4(0, 0, myProjCamera.getZScreen(), 1.0f);
43
+            aTestProj /= aTestProj.w();
44
+            aTestProj.x() = 0.5f + aTestProj.x() * 0.5f;
45
+            aTestProj.y() = 0.5f + aTestProj.y() * 0.5f;
46
+
47
+            myScrDispX   = float((aTestProj.x() - 0.5f) * myRectGl.width());
48
+            myScrDispXPx = int(double(aTestProj.x()) * double(myViewport[2]) - double(myViewport[2])/2);
49
+            //myScrDispYPx = int(double(aTestProj.y()) * double(myViewport[3]) - double(myViewport[3])/2);
50
+        } else {
51
+            if(theView == ST_DRAW_LEFT) {
52
+                myScrDispX   =             myLensDist * float(0.5 * myRectGl.width());
53
+                myScrDispXPx =  int(double(myLensDist) * 0.5 * double(myViewport[2]));
54
+            } else {
55
+                myScrDispX   =            -myLensDist * float(0.5 * myRectGl.width());
56
+                myScrDispXPx = -int(double(myLensDist) * 0.5 * double(myViewport[2]));
57
+            }
58
+        }
59
     }
60
 
61
     StGLWidget::stglDraw(theView);
62
@@ -314,8 +310,9 @@
63
     StGLWidget::stglUpdate(theCursorZo, theIsPreciseInput);
64
 }
65
 
66
-void StGLRootWidget::stglScissorRect(const StRectI_t& theRect,
67
-                                     StGLBoxPx&       theScissorRect) const {
68
+void StGLRootWidget::stglScissorRectInternal(const StRectI_t& theRect,
69
+                                             const bool theIs2d,
70
+                                             StGLBoxPx& theScissorRect) const {
71
     const GLint aVPortWidth  = myViewport[2];
72
     const GLint aVPortHeight = myViewport[3];
73
     const GLint aRootWidth   = myRectPxFull.width();
74
@@ -330,7 +327,8 @@
75
     const GLdouble aWidthFactor  = GLdouble(aVPortWidth)  / GLdouble(aRootWidth);
76
     const GLdouble aHeightFactor = GLdouble(aVPortHeight) / GLdouble(aRootHeight);
77
 
78
-    theScissorRect.x() = myViewport[0] + GLint(aWidthFactor  * GLdouble(theRect.left() + myScrDispXPx));
79
+    const int anEyeShiftPx = theIs2d ? myScrDispXPx : 0;
80
+    theScissorRect.x() = myViewport[0] + GLint(aWidthFactor  * GLdouble(theRect.left() + anEyeShiftPx));
81
     theScissorRect.y() = myViewport[1] + GLint(aHeightFactor * GLdouble(aRootHeight - theRect.bottom()));
82
 
83
     theScissorRect.width()  = GLint(aWidthFactor  * GLdouble(theRect.width()));
84
@@ -370,6 +368,16 @@
85
         myMenuProgram->setProjMat(*myGlCtx, getScreenProjection());
86
         myMenuProgram->unuse(*myGlCtx);
87
     }
88
+    if(myTextProgram->isValid()) {
89
+        myTextProgram->use(*myGlCtx);
90
+        myTextProgram->setProjMat(*myGlCtx, getScreenProjection());
91
+        myTextProgram->unuse(*myGlCtx);
92
+    }
93
+    if(myTextBorderProgram->isValid()) {
94
+        myTextBorderProgram->use(*myGlCtx);
95
+        myTextBorderProgram->setProjMat(*myGlCtx, getScreenProjection());
96
+        myTextBorderProgram->unuse(*myGlCtx);
97
+    }
98
 
99
     // update all child widgets
100
     if(isChanged) {
101
sview-17_04.tar.gz/StGLWidgets/StGLScrollArea.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLScrollArea.cpp Changed
63
 
1
@@ -27,7 +27,8 @@
2
   myDragYCumul(0),
3
   myFlingAccel((double )myRoot->scale(200)),
4
   myFlingYSpeed(0.0),
5
-  myFlingYDone(0) {
6
+  myFlingYDone(0),
7
+  myScrollYAccum(0.0f) {
8
     //
9
 }
10
 
11
@@ -167,7 +168,7 @@
12
     }
13
 
14
     StGLBoxPx aScissorRect;
15
-    stglScissorRect(aScissorRect);
16
+    stglScissorRect2d(aScissorRect);
17
     aCtx.stglSetScissorRect(aScissorRect, true);
18
 
19
     StGLWidget::stglDraw(theView); // draw children
20
@@ -274,8 +275,12 @@
21
 
22
 bool StGLScrollArea::tryUnClick(const StClickEvent& theEvent,
23
                                 bool&               theIsItemUnclicked) {
24
+    bool toCancel = false;
25
     if(myIsLeftClick
26
     && theEvent.Button == ST_MOUSE_LEFT) {
27
+        if(myHasDragged) {
28
+            toCancel = true;
29
+        }
30
         myIsLeftClick = false;
31
         myHasDragged  = false;
32
         if(myDragTimer.isOn()) {
33
@@ -290,6 +295,11 @@
34
             }
35
         }
36
     }
37
+    if(toCancel) {
38
+        StClickEvent anEvent = theEvent;
39
+        anEvent.Type = stEvent_MouseCancel;
40
+        return StGLWidget::tryUnClick(anEvent, theIsItemUnclicked);
41
+    }
42
     return StGLWidget::tryUnClick(theEvent, theIsItemUnclicked);
43
 }
44
 
45
@@ -298,11 +308,12 @@
46
         return true;
47
     }
48
 
49
-    int aDeltaY = (int )fabs(theEvent.DeltaY * 2.0f);
50
-    if(theEvent.DeltaY > 0.001f) {
51
-        doScroll( myRoot->scale(aDeltaY));
52
-    } else if(theEvent.DeltaY < -0.001f) {
53
-        doScroll(-myRoot->scale(aDeltaY));
54
+    myScrollYAccum += theEvent.DeltaY * 20.0f;
55
+    const int aDeltaY = (int )myScrollYAccum;
56
+    if(aDeltaY != 0) {
57
+        myScrollYAccum -= float(aDeltaY);
58
+        const int aDeltaScaled = myRoot->scale(std::abs(aDeltaY));
59
+        doScroll(aDeltaY > 0 ? aDeltaScaled : -aDeltaScaled);
60
     }
61
     return true;
62
 }
63
sview-17_04.tar.gz/StGLWidgets/StGLSeekBar.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLSeekBar.cpp Changed
59
 
1
@@ -233,13 +233,29 @@
2
         return;
3
     }
4
 
5
-    const double aPos   = stMin(stMax(getPointInEx(theCursor), 0.0), 1.0);
6
-    const int    aPosPx = int(aPos * double(getRectPx().width()));
7
-
8
+    const int aRoundTol = myRoot->scale(1);
9
+    const int aMaxPosPx = getRectPx().width();
10
+    double aPos   = stMin(stMax(getPointInEx(theCursor), 0.0), 1.0);
11
+    int    aPosPx = int(aPos * double(aMaxPosPx));
12
     const int aMoveTolerPx = myMoveTolerPx > 0 ? myMoveTolerPx : myRoot->scale(theIsPreciseInput ? 1 : 2);
13
-    if(myClickPos >= 0
14
-    && std::abs(aPosPx - myClickPos) < aMoveTolerPx) {
15
-        return;
16
+    if(std::abs(aPosPx - 0) <= aRoundTol) {
17
+        aPos   = 0.0;
18
+        aPosPx = 0;
19
+    } else if(std::abs(aPosPx - aMaxPosPx) <= aRoundTol) {
20
+        aPos   = 1.0;
21
+        aPosPx = aMaxPosPx;
22
+    }
23
+
24
+    if(myClickPos >= 0) {
25
+        if(myClickPos == aPosPx) {
26
+            return;
27
+        }
28
+
29
+        if(aPosPx != 0
30
+        && aPosPx != aMaxPosPx
31
+        && std::abs(aPosPx - myClickPos) < aMoveTolerPx) {
32
+            return;
33
+        }
34
     }
35
 
36
     myClickPos = aPosPx;
37
@@ -260,9 +276,18 @@
38
 }
39
 
40
 void StGLSeekBar::doMouseUnclick(const int mouseBtn) {
41
-    const double aPos       = stMin(stMax(getPointInEx(myRoot->getCursorZo()), 0.0), 1.0);
42
-    const int    aTolerance = myRoot->scale(1);
43
-    const int    aPosPx     = int(aPos * double(getRectPx().width()));
44
+    const int aTolerance = myRoot->scale(1);
45
+    const int aMaxPosPx  = getRectPx().width();
46
+    double aPos   = stMin(stMax(getPointInEx(myRoot->getCursorZo()), 0.0), 1.0);
47
+    int    aPosPx = int(aPos * double(aMaxPosPx));
48
+    if(std::abs(aPosPx - 0) <= aTolerance) {
49
+        aPos   = 0.0;
50
+        aPosPx = 0;
51
+    } else if(std::abs(aPosPx - aMaxPosPx) <= aTolerance) {
52
+        aPos   = 1.0;
53
+        aPosPx = aMaxPosPx;
54
+    }
55
+
56
     if(myClickPos >= 0
57
     && std::abs(aPosPx - myClickPos) < aTolerance) {
58
         myClickPos = -1;
59
sview-17_04.tar.gz/StGLWidgets/StGLSubtitles.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLSubtitles.cpp Changed
313
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -11,10 +11,12 @@
10
 
11
 #include <StGLCore/StGLCore20.h>
12
 #include <StGL/StGLProgram.h>
13
+#include <StGLWidgets/StGLImageRegion.h>
14
 #include <StGLWidgets/StGLRootWidget.h>
15
 
16
 namespace {
17
     static const size_t SHARE_IMAGE_PROGRAM_ID = StGLRootWidget::generateShareId();
18
+    static StGLVCorner parseCorner(int theVal) { return (StGLVCorner )theVal; }
19
 }
20
 
21
 class StGLSubtitles::StImgProgram : public StGLProgram {
22
@@ -87,7 +89,7 @@
23
 };
24
 
25
 StGLSubtitles::StSubShowItems::StSubShowItems()
26
-: StArrayList<StHandle <StSubItem> >(8) {
27
+: StArrayList<StHandle <StSubItem> >(8), Scale (1.0f) {
28
     //
29
 }
30
 
31
@@ -121,8 +123,10 @@
32
     const StImagePlane& anImage = getFirst()->Image;
33
     if(!anImage.isNull()) {
34
         Image.initCopy(anImage, false);
35
+        Scale = getFirst()->Scale;
36
     } else {
37
         Image.nullify();
38
+        Scale = 1.0f;
39
     }
40
 
41
     return isChanged;
42
@@ -137,36 +141,31 @@
43
     const StImagePlane& anImage = theItem->Image;
44
     if(!anImage.isNull()) {
45
         Image.initCopy(anImage, false);
46
+        Scale = theItem->Scale;
47
     }
48
 
49
     StArrayList<StHandle <StSubItem> >::add(theItem);
50
 }
51
 
52
-inline StGLVCorner parseCorner(int theVal) {
53
-    return (StGLVCorner )theVal;
54
-}
55
-
56
-StGLSubtitles::StGLSubtitles(StGLWidget*                     theParent,
57
+StGLSubtitles::StGLSubtitles(StGLImageRegion* theParent,
58
                              const StHandle<StSubQueue>&     theSubQueue,
59
                              const StHandle<StInt32Param>&   thePlace,
60
-                             const StHandle<StFloat32Param>& theTopDY,
61
-                             const StHandle<StFloat32Param>& theBottomDY,
62
-                             const StHandle<StFloat32Param>& theFontSize,
63
-                             const StHandle<StFloat32Param>& theParallax,
64
-                             const StHandle<StEnumParam>&    theParser)
65
+                             const StHandle<StFloat32Param>& theFontSize)
66
 : StGLTextArea(theParent,
67
                0, 0,
68
                StGLCorner(parseCorner(thePlace->getValue()), ST_HCORNER_CENTER),
69
                theParent->getRoot()->scale(800), theParent->getRoot()->scale(160)),
70
-  myPlace(thePlace),
71
-  myTopDY(theTopDY),
72
-  myBottomDY(theBottomDY),
73
-  myFontSize(theFontSize),
74
-  myParallax(theParallax),
75
-  myParser(theParser),
76
   myQueue(theSubQueue),
77
   myPTS(0.0),
78
   myImgProgram(getRoot()->getShare(SHARE_IMAGE_PROGRAM_ID)) {
79
+    params.Place    = thePlace;
80
+    params.FontSize = theFontSize;
81
+    params.TopDY    = new StFloat32Param(100.0f);
82
+    params.BottomDY = new StFloat32Param(100.0f);
83
+    params.Parallax = new StFloat32Param(0.0f);
84
+    params.Parser   = new StEnumParam(1, stCString("subsParser"));
85
+    params.ToApplyStereo = new StBoolParamNamed(true, stCString("subsApplyStereo"));
86
+
87
     if(myQueue.isNull()) {
88
         myQueue = new StSubQueue();
89
     }
90
@@ -180,7 +179,7 @@
91
 
92
     StHandle<StGLFont> aFontNew = new StGLFont();
93
     StHandle<StFTLibrary> aLib = getRoot()->getFontManager()->getLibraty();
94
-    const FontSize     aSize       = (FontSize )(int )myFontSize->getValue();
95
+    const FontSize     aSize       = (FontSize )(int )params.FontSize->getValue();
96
     const unsigned int aResolution = getRoot()->getFontManager()->getResolution();
97
     for(size_t anIter = 0; anIter < StFTFont::SubsetsNB; ++anIter) {
98
         StHandle<StGLFontEntry>& aFontGlSrc = myFont->changeFont((StFTFont::Subset )anIter);
99
@@ -190,7 +189,9 @@
100
 
101
         StHandle<StFTFont> aFontFt = new StFTFont(aLib);
102
         for(int aStyleIt = 0; aStyleIt < StFTFont::StylesNB; ++aStyleIt) {
103
-            aFontFt->load(aFontGlSrc->getFont()->getFilePath((StFTFont::Style )aStyleIt), (StFTFont::Style )aStyleIt);
104
+            aFontFt->load(aFontGlSrc->getFont()->getFilePath((StFTFont::Style )aStyleIt),
105
+                          aFontGlSrc->getFont()->getFaceIndex((StFTFont::Style )aStyleIt),
106
+                          (StFTFont::Style )aStyleIt);
107
         }
108
         aFontFt->init(aSize, aResolution);
109
         aFontNew->changeFont((StFTFont::Subset )anIter) = new StGLFontEntry(aFontFt);
110
@@ -211,15 +212,10 @@
111
 bool StGLSubtitles::stglInit() {
112
     if(!myVertBuf.isValid()) {
113
         StArray<StGLVec2> aDummyVert(4);
114
-        StArray<StGLVec2> aTexCoords(4);
115
-        aTexCoords[0] = StGLVec2(1.0f, 0.0f);
116
-        aTexCoords[1] = StGLVec2(1.0f, 1.0f);
117
-        aTexCoords[2] = StGLVec2(0.0f, 0.0f);
118
-        aTexCoords[3] = StGLVec2(0.0f, 1.0f);
119
 
120
         StGLContext& aCtx = getContext();
121
         myVertBuf.init(aCtx, aDummyVert);
122
-        myTCrdBuf.init(aCtx, aTexCoords);
123
+        myTCrdBuf.init(aCtx, aDummyVert);
124
 
125
         if(myImgProgram.isNull()) {
126
             myImgProgram.create(getRoot()->getContextHandle(), new StImgProgram());
127
@@ -237,12 +233,12 @@
128
         myShowItems.add(aNewSubItem);
129
     }
130
 
131
-    const StGLVCorner aCorner = parseCorner(myPlace->getValue());
132
+    const StGLVCorner aCorner = parseCorner(params.Place->getValue());
133
     bool toResize = myCorner.v != aCorner;
134
     myCorner.v = aCorner;
135
     switch(myCorner.v) {
136
         case ST_VCORNER_TOP: {
137
-            const int aDisp = myRoot->scale((int )myTopDY->getValue()) + myRoot->getRootMargins().top;
138
+            const int aDisp = myRoot->scale((int )params.TopDY->getValue()) + myRoot->getRootMargins().top;
139
             if(getRectPx().top() != aDisp) {
140
                 toResize = true;
141
                 changeRectPx().moveTopTo(aDisp);
142
@@ -261,7 +257,7 @@
143
             break;
144
         }
145
         case ST_VCORNER_BOTTOM: {
146
-            const int aDisp = -myRoot->scale((int )myBottomDY->getValue()) - myRoot->getRootMargins().bottom;
147
+            const int aDisp = -myRoot->scale((int )params.BottomDY->getValue()) - myRoot->getRootMargins().bottom;
148
             if(getRectPx().top() != aDisp) {
149
                 toResize = true;
150
                 changeRectPx().moveTopTo(aDisp);
151
@@ -292,7 +288,7 @@
152
         ST_DEBUG_LOG("(" + myPTS + ") myShowItems.myText= '" + myShowItems.myText + "'\n" + aLog);*/
153
     }
154
 
155
-    const FontSize aNewSize = (FontSize )(int )myFontSize->getValue();
156
+    const FontSize aNewSize = (FontSize )(int )params.FontSize->getValue();
157
     if(!myText.isEmpty()
158
     && aNewSize != mySize) {
159
         mySize = aNewSize;
160
@@ -308,8 +304,8 @@
161
     }
162
 
163
     StGLContext& aCtx = getContext();
164
-    if(myFormatter.getParser() != (StGLTextFormatter::Parser )myParser->getValue()) {
165
-        myFormatter.setupParser((StGLTextFormatter::Parser )myParser->getValue());
166
+    if(myFormatter.getParser() != (StGLTextFormatter::Parser )params.Parser->getValue()) {
167
+        myFormatter.setupParser((StGLTextFormatter::Parser )params.Parser->getValue());
168
         myToRecompute = true;
169
     }
170
     if(!myText.isEmpty()) {
171
@@ -317,10 +313,10 @@
172
 
173
         switch(theView) {
174
             case ST_DRAW_LEFT:
175
-                myTextDX = -myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
176
+                myTextDX = -params.Parallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
177
                 break;
178
             case ST_DRAW_RIGHT:
179
-                myTextDX =  myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
180
+                myTextDX =  params.Parallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
181
                 break;
182
             case ST_DRAW_MONO:
183
             default:
184
@@ -335,20 +331,120 @@
185
         return;
186
     }
187
 
188
-    aCtx.core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
189
-    aCtx.core20fwd->glEnable(GL_BLEND);
190
-    myTexture.bind(aCtx);
191
+    StHandle<StStereoParams> aParams;
192
+    StFormat aStFormat = StFormat_Mono;
193
+    unsigned int aView = theView;
194
+    float aSampleRatio = 1.0f;
195
+    StVec2<int> aFrameDims(0, 0);
196
+    if(StGLImageRegion* anImgRegion = !params.ToApplyStereo.isNull() && params.ToApplyStereo->getValue()
197
+                                    ? dynamic_cast<StGLImageRegion*>(myParent)
198
+                                    : NULL) {
199
+        aParams = anImgRegion->getSource();
200
+        if(!aParams.isNull()) {
201
+            aStFormat = aParams->StereoFormat;
202
+            aSampleRatio = anImgRegion->getSampleRatio();
203
+            aFrameDims   = anImgRegion->getFrameSize();
204
+            if(aParams->ToSwapLR) {
205
+                // apply swap flag
206
+                switch(aStFormat) {
207
+                    case StFormat_SideBySide_LR: aStFormat = StFormat_SideBySide_RL; break;
208
+                    case StFormat_SideBySide_RL: aStFormat = StFormat_SideBySide_LR; break;
209
+                    case StFormat_TopBottom_LR:  aStFormat = StFormat_TopBottom_RL;  break;
210
+                    case StFormat_TopBottom_RL:  aStFormat = StFormat_TopBottom_LR;  break;
211
+                    default: break;
212
+                }
213
+            }
214
+            // swap views
215
+            if(aStFormat == StFormat_SideBySide_RL) {
216
+                aStFormat = StFormat_SideBySide_LR;
217
+                if(theView == ST_DRAW_RIGHT) {
218
+                    aView = ST_DRAW_LEFT;
219
+                } else if(theView == ST_DRAW_LEFT) {
220
+                    aView = ST_DRAW_RIGHT;
221
+                }
222
+            } else if(aStFormat == StFormat_TopBottom_RL) {
223
+                aStFormat = StFormat_TopBottom_LR;
224
+                if(theView == ST_DRAW_RIGHT) {
225
+                    aView = ST_DRAW_LEFT;
226
+                } else if(theView == ST_DRAW_LEFT) {
227
+                    aView = ST_DRAW_RIGHT;
228
+                }
229
+            }
230
+            // reset
231
+            if(aStFormat != StFormat_SideBySide_LR
232
+            && aStFormat != StFormat_TopBottom_LR) {
233
+                aSampleRatio = 1.0f;
234
+            }
235
+        }
236
+    }
237
 
238
     // update vertices
239
-    StRectI_t aRect = getRectPxAbsolute();
240
-    aRect.top()   = aRect.bottom() - myTexture.getSizeY();
241
-    aRect.left()  = aRect.left() + aRect.width() / 2 - myTexture.getSizeX() / 2;
242
-    aRect.right() = aRect.left() + myTexture.getSizeX();
243
+    StVec2<int> anImgSize (myTexture.getSizeX(), myTexture.getSizeY()), anOffset (0, 0);
244
+    StArray<StGLVec2> aVertices(4), aTexCoords(4);
245
+    aTexCoords[0] = StGLVec2(1.0f, 0.0f);
246
+    aTexCoords[1] = StGLVec2(1.0f, 1.0f);
247
+    aTexCoords[2] = StGLVec2(0.0f, 0.0f);
248
+    aTexCoords[3] = StGLVec2(0.0f, 1.0f);
249
+    if(aSampleRatio >= 1.0f) {
250
+        anImgSize.x() = int(double(anImgSize.x()) * aSampleRatio);
251
+    } else {
252
+        anImgSize.y() = int(double(anImgSize.y()) / aSampleRatio);
253
+    }
254
+    const double aFontScale = double(getRoot()->getScale()) * myShowItems.Scale * params.FontSize->getValue() / params.FontSize->getDefValue();
255
+    anImgSize.x() = int(double(anImgSize.x()) * aFontScale);
256
+    anImgSize.y() = int(double(anImgSize.y()) * aFontScale);
257
+
258
+    switch(aStFormat) {
259
+        case StFormat_SideBySide_LR: {
260
+            anImgSize.x() /= 2;
261
+            const int anOffsetX = int(aFontScale * ((aFrameDims.x() * 2 - myTexture.getSizeX()) / 2));
262
+            if(aView == ST_DRAW_LEFT) {
263
+                aTexCoords[0].x() = aTexCoords[1].x() = 0.5f;
264
+                aTexCoords[2].x() = aTexCoords[3].x() = 0.0f;
265
+                anOffset.x() = anOffsetX;
266
+            } else if(aView == ST_DRAW_RIGHT) {
267
+                aTexCoords[0].x() = aTexCoords[1].x() = 1.0f;
268
+                aTexCoords[2].x() = aTexCoords[3].x() = 0.5f;
269
+                anOffset.x() = -anOffsetX;
270
+            }
271
+            break;
272
+        }
273
+        case StFormat_TopBottom_LR: {
274
+            anImgSize.y() /= 2;
275
+            const int anOffsetY = int(aFontScale * ((aFrameDims.y() * 2 - myTexture.getSizeY()) / 2));
276
+            if(aView == ST_DRAW_LEFT) {
277
+                aTexCoords[0].y() = aTexCoords[2].y() = 0.0f;
278
+                aTexCoords[1].y() = aTexCoords[3].y() = 0.5f;
279
+                anOffset.y() = -anOffsetY;
280
+            } else if(aView == ST_DRAW_RIGHT) {
281
+                aTexCoords[0].y() = aTexCoords[2].y() = 0.5f;
282
+                aTexCoords[1].y() = aTexCoords[3].y() = 1.0f;
283
+                anOffset.y() = anOffsetY;
284
+            }
285
+            break;
286
+        }
287
+        default: {
288
+            break;
289
+        }
290
+    }
291
+    if(aView == ST_DRAW_LEFT) {
292
+        anOffset.x() -= (int )params.Parallax->getValue();
293
+    } else if(aView == ST_DRAW_RIGHT) {
294
+        anOffset.x() += (int )params.Parallax->getValue();
295
+    }
296
 
297
-    StArray<StGLVec2> aVertices(4);
298
+    StRectI_t aRect = getRectPxAbsolute();
299
+    aRect.bottom() += anOffset.y();
300
+    aRect.top()   = aRect.bottom() - anImgSize.y();
301
+    aRect.left()  = aRect.left() + aRect.width() / 2 - anImgSize.x() / 2 + anOffset.x();
302
+    aRect.right() = aRect.left() + anImgSize.x();
303
     myRoot->getRectGl(aRect, aVertices);
304
     myVertBuf.init(aCtx, aVertices);
305
+    myTCrdBuf.init(aCtx, aTexCoords);
306
 
307
+    aCtx.core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
308
+    aCtx.core20fwd->glEnable(GL_BLEND);
309
+    myTexture.bind(aCtx);
310
     myImgProgram->use(aCtx);
311
 
312
     myVertBuf.bindVertexAttrib(aCtx, myImgProgram->getVVertexLoc());
313
sview-17_04.tar.gz/StGLWidgets/StGLTable.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLTable.cpp Changed
75
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2014-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2014-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -12,6 +12,7 @@
10
 #include <StGLWidgets/StGLCombobox.h>
11
 #include <StGLWidgets/StGLCheckbox.h>
12
 #include <StGLWidgets/StGLMenuItem.h>
13
+#include <StGLWidgets/StGLRangeFieldFloat32.h>
14
 #include <StGLWidgets/StGLRootWidget.h>
15
 
16
 #include <StGL/StGLContext.h>
17
@@ -19,6 +20,7 @@
18
 
19
 #include <StStrings/StDictionary.h>
20
 #include <StSettings/StEnumParam.h>
21
+#include <StSettings/StFloat32Param.h>
22
 
23
 #include <stAssert.h>
24
 
25
@@ -165,6 +167,7 @@
26
     int aCol2Width = 0;
27
     StHandle<StBoolParamNamed> aBool;
28
     StHandle<StEnumParam>      anEnum;
29
+    StHandle<StFloat32Param>   aFloat32;
30
     const int anIconMargin = myRoot->scale(8);
31
     const int anIconWidth  = anIconMargin * 2 + myRoot->scale(16);
32
     StMarginsI aCheckMargins;
33
@@ -194,6 +197,18 @@
34
             for(size_t aValIter = 0; aValIter < aValues.size(); ++aValIter) {
35
                 aCol2Width = stMax(aCol2Width, aButton->computeWidth(aValues[aValIter]));
36
             }
37
+        } else if(aFloat32.downcastFrom(aParam)) {
38
+            StGLRangeFieldFloat32* aRange = new StGLRangeFieldFloat32(&anItem, aFloat32,
39
+                                                                      0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT),
40
+                                                                      StGLRangeFieldFloat32::RangeStyle_Seekbar, myRoot->scale(18));
41
+            aRange->changeRectPx().right() = myRoot->scale(50);
42
+            aRange->changeMargins().left   = myRoot->scale(8);
43
+            aRange->changeMargins().right  = myRoot->scale(8);
44
+            aRange->setCorner(StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
45
+            if(!aFloat32->getFormat().isEmpty()) {
46
+                aRange->setFormat(aFloat32->getFormat());
47
+            }
48
+            aCol2Width = stMax(aCol2Width, aRange->getRectPx().width());
49
         } else {
50
             // skip
51
         }
52
@@ -209,10 +224,11 @@
53
             continue;
54
         }
55
 
56
-        StGLCombobox* aButton = dynamic_cast<StGLCombobox* >(anItem.getItem());
57
-        if(aButton != NULL) {
58
+        if(StGLCombobox* aButton = dynamic_cast<StGLCombobox* >(anItem.getItem())) {
59
             anItem.getItem()->changeRectPx().right() = aWidget->getRectPx().left() + aCol2Width;
60
             aButton->setWidth(aCol2Width);
61
+        } else if(dynamic_cast<StGLRangeFieldFloat32* >(anItem.getItem()) != NULL) {
62
+            anItem.getItem()->changeRectPx().right() = aWidget->getRectPx().left() + aCol2Width;
63
         }
64
     }
65
 
66
@@ -229,6 +245,8 @@
67
             aLabelText = aBool->getName();
68
         } else if(anEnum.downcastFrom(aParam)) {
69
             aLabelText = anEnum->getName();
70
+        } else if(aFloat32.downcastFrom(aParam)) {
71
+            aLabelText = aFloat32->getName();
72
         } else {
73
             // skip
74
         }
75
sview-17_04.tar.gz/StGLWidgets/StGLTextArea.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLTextArea.cpp Changed
71
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -273,15 +273,8 @@
10
     StRectD_t aTextRectGl = getRoot()->getRectGl(getAbsolute(aTextRectPx));
11
 
12
     // size corrector for FTGL
13
-    StRectD_t zparams; getCamera()->getZParams(zparams);
14
-    GLfloat aSizeOut = 2.0f * GLfloat(zparams.top()) / GLfloat(getRoot()->getRootFullSizeY());
15
-
16
-    StGLMatrix aModelMat;
17
-    aModelMat.translate(StGLVec3(getRoot()->getScreenDispX() + myTextDX, 0.0f, -getCamera()->getZScreen()));
18
-    aModelMat.translate(StGLVec3(GLfloat(aTextRectGl.left()),
19
-                                 GLfloat(aTextRectGl.top()),
20
-                                 0.0f));
21
-    aModelMat.scale(aSizeOut, aSizeOut, 0.0f);
22
+    StRectD_t aZParams; getCamera()->getZParams(aZParams);
23
+    const GLfloat aSizeOut = 2.0f * GLfloat(aZParams.top()) / GLfloat(getRoot()->getRootFullSizeY());
24
 
25
     aCtx.core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
26
     aCtx.core20fwd->glEnable(GL_BLEND);
27
@@ -294,7 +287,10 @@
28
 
29
         StGLTextBorderProgram& aBorderProgram = myRoot->getTextBorderProgram();
30
         aBorderProgram.use(aCtx);
31
-        aBorderProgram.setModelMat(aCtx, aModelMat);
32
+        aBorderProgram.setDisplacement(aCtx,
33
+                                       StGLVec3(GLfloat(aTextRectGl.left()) + getRoot()->getScreenDispX() + myTextDX,
34
+                                                GLfloat(aTextRectGl.top()), 0.0f),
35
+                                       aSizeOut);
36
 
37
         aBorderProgram.setColor(aCtx, myBorderColor);
38
         myBorderOVertBuf.bindVertexAttrib(aCtx, aBorderProgram.getVVertexLoc());
39
@@ -312,23 +308,22 @@
40
     aCtx.core20fwd->glActiveTexture(GL_TEXTURE0); // our shader is bound to first texture unit
41
     StGLTextProgram& aTextProgram = myRoot->getTextProgram();
42
     aTextProgram.use(aCtx);
43
-        aTextProgram.setModelMat(aCtx, aModelMat);
44
+        aTextProgram.setDisplacement(aCtx,
45
+                                     StGLVec3(GLfloat(aTextRectGl.left()) + getRoot()->getScreenDispX() + myTextDX,
46
+                                              GLfloat(aTextRectGl.top()), 0.0f),
47
+                                     aSizeOut);
48
         aTextProgram.setColor(aCtx, myToDrawShadow ? myShadowColor : aTextColor);
49
-
50
         drawText(aCtx);
51
 
52
         if(myToDrawShadow) {
53
-            aModelMat.initIdentity();
54
             aTextRectPx.left() -= 1;
55
             aTextRectPx.top()  -= 1;
56
             aTextRectGl = getRoot()->getRectGl(getAbsolute(aTextRectPx));
57
-            aModelMat.translate(StGLVec3(getRoot()->getScreenDispX() + myTextDX, 0.0f, -getCamera()->getZScreen()));
58
-            aModelMat.translate(StGLVec3(GLfloat(aTextRectGl.left()),
59
-                                         GLfloat(aTextRectGl.top()),
60
-                                         0.0f));
61
-            aModelMat.scale(aSizeOut, aSizeOut, 0.0f);
62
 
63
-            aTextProgram.setModelMat(aCtx, aModelMat);
64
+            aTextProgram.setDisplacement(aCtx,
65
+                                         StGLVec3(GLfloat(aTextRectGl.left()) + getRoot()->getScreenDispX() + myTextDX,
66
+                                                  GLfloat(aTextRectGl.top()), 0.0f),
67
+                                         aSizeOut);
68
             aTextProgram.setColor(aCtx, aTextColor);
69
 
70
             drawText(aCtx);
71
sview-17_04.tar.gz/StGLWidgets/StGLTextBorderProgram.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLTextBorderProgram.cpp Changed
48
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -27,9 +27,10 @@
10
     theCtx.core20fwd->glUniformMatrix4fv(myUniformProjMat, 1, GL_FALSE, theProjMat);
11
 }
12
 
13
-void StGLTextBorderProgram::setModelMat(StGLContext&      theCtx,
14
-                                        const StGLMatrix& theModelMat) {
15
-    theCtx.core20fwd->glUniformMatrix4fv(myUniformModelMat, 1, GL_FALSE, theModelMat);
16
+void StGLTextBorderProgram::setDisplacement(StGLContext& theCtx,
17
+                                            const StGLVec3& theDisp,
18
+                                            const float theScale) {
19
+    theCtx.core20fwd->glUniform4fv(myUniformDispl, 1, StGLVec4(theDisp, theScale));
20
 }
21
 
22
 void StGLTextBorderProgram::setColor(StGLContext&    theCtx,
23
@@ -40,10 +41,10 @@
24
 bool StGLTextBorderProgram::init(StGLContext& theCtx) {
25
     const char VERTEX_SHADER[] =
26
        "uniform mat4 uProjMat; \
27
-        uniform mat4 uModelMat; \
28
+        uniform vec4 uDisp; \
29
         attribute vec4 vVertex; \
30
         void main(void) { \
31
-            gl_Position = uProjMat * uModelMat * vVertex; \
32
+            gl_Position = uProjMat * (vec4(vVertex.xy * uDisp.w, 0.0, 1.0) + vec4(uDisp.xyz, 0.0)); \
33
         }";
34
 
35
     const char FRAGMENT_SHADER[] =
36
@@ -68,9 +69,9 @@
37
     }
38
 
39
     myUniformProjMat  = StGLProgram::getUniformLocation(theCtx, "uProjMat");
40
-    myUniformModelMat = StGLProgram::getUniformLocation(theCtx, "uModelMat");
41
+    myUniformDispl    = StGLProgram::getUniformLocation(theCtx, "uDisp");
42
     myUniformColor    = StGLProgram::getUniformLocation(theCtx, "uColor");
43
     return myUniformProjMat.isValid()
44
-        && myUniformModelMat.isValid()
45
+        && myUniformDispl.isValid()
46
         && myUniformColor.isValid();
47
 }
48
sview-17_04.tar.gz/StGLWidgets/StGLTextProgram.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLTextProgram.cpp Changed
57
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -27,9 +27,10 @@
10
     theCtx.core20fwd->glUniformMatrix4fv(myUniformProjMat, 1, GL_FALSE, theProjMat);
11
 }
12
 
13
-void StGLTextProgram::setModelMat(StGLContext&      theCtx,
14
-                                  const StGLMatrix& theModelMat) {
15
-    theCtx.core20fwd->glUniformMatrix4fv(myUniformModelMat, 1, GL_FALSE, theModelMat);
16
+void StGLTextProgram::setDisplacement(StGLContext& theCtx,
17
+                                      const StGLVec3& theDisp,
18
+                                      const float theScale) {
19
+    theCtx.core20fwd->glUniform4fv(myUniformDispl, 1, StGLVec4(theDisp, theScale));
20
 }
21
 
22
 void StGLTextProgram::setColor(StGLContext&    theCtx,
23
@@ -40,13 +41,13 @@
24
 bool StGLTextProgram::init(StGLContext& theCtx) {
25
     const char VERTEX_SHADER[] =
26
        "uniform mat4 uProjMat; \
27
-        uniform mat4 uModelMat; \
28
+        uniform vec4 uDisp; \
29
         attribute vec4 vVertex; \
30
         attribute vec2 vTexCoord; \
31
         varying vec2 fTexCoord; \
32
         void main(void) { \
33
             fTexCoord = vTexCoord; \
34
-            gl_Position = uProjMat * uModelMat * vVertex; \
35
+            gl_Position = uProjMat * (vec4(vVertex.xy * uDisp.w, 0.0, 1.0) + vec4(uDisp.xyz, 0.0)); \
36
         }";
37
 
38
     const char FRAGMENT_GET_RED[] =
39
@@ -84,7 +85,7 @@
40
     }
41
 
42
     myUniformProjMat  = StGLProgram::getUniformLocation(theCtx, "uProjMat");
43
-    myUniformModelMat = StGLProgram::getUniformLocation(theCtx, "uModelMat");
44
+    myUniformDispl    = StGLProgram::getUniformLocation(theCtx, "uDisp");
45
     myUniformColor    = StGLProgram::getUniformLocation(theCtx, "uTextColor");
46
 
47
     StGLVarLocation aUniformTexture = StGLProgram::getUniformLocation(theCtx, "uTexture");
48
@@ -95,7 +96,7 @@
49
     }
50
 
51
     return myUniformProjMat.isValid()
52
-        && myUniformModelMat.isValid()
53
+        && myUniformDispl.isValid()
54
         && myUniformColor.isValid()
55
         && aUniformTexture.isValid();
56
 }
57
sview-17_04.tar.gz/StGLWidgets/StGLTextureButton.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLTextureButton.cpp Changed
72
 
1
@@ -222,26 +222,20 @@
2
      * Initialize all programs.
3
      */
4
     bool init(StGLContext& theCtx) {
5
-        /**const char FRAGMENT_GET_RED[] =
6
+        const char* FRAGMENT_GET_ALPHA = theCtx.arbTexRG
7
+                                       ? "#define stTextureAlpha(theSampler, theCoords) texture2D(theSampler, theCoords).r\n"
8
+                                       : "#define stTextureAlpha(theSampler, theCoords) texture2D(theSampler, theCoords).a\n";
9
+        const char FRAGMENT_GET_COLOR[] =
10
             "uniform sampler2D uTexture;\n"
11
             "uniform vec4      uColor;\n"
12
             "vec4 getColor(in vec2 theTexCoord) {\n"
13
             "     vec4 aColor = uColor;\n"
14
-            "     aColor.a *= 1.0 - texture2D(uTexture, theTexCoord).r;\n"
15
-            "     return aColor;\n"
16
-            "}\n\n";*/
17
-
18
-        const char FRAGMENT_GET_ALPHA[] =
19
-            "uniform sampler2D uTexture;\n"
20
-            "uniform vec4      uColor;\n"
21
-            "vec4 getColor(in vec2 theTexCoord) {\n"
22
-            "     vec4 aColor = uColor;\n"
23
-            "     aColor.a *= 1.0 - texture2D(uTexture, theTexCoord).a;\n"
24
+            "     aColor.a *= 1.0 - stTextureAlpha(uTexture, theTexCoord);\n"
25
             "     return aColor;\n"
26
             "}\n\n";
27
+
28
         registerFragmentShaderPart(FragSection_GetColor, FragGetColor_Alpha,
29
-                                   ///theCtx.arbTexRG ? FRAGMENT_GET_RED :
30
-                                     FRAGMENT_GET_ALPHA);
31
+                                   StString(FRAGMENT_GET_ALPHA) + FRAGMENT_GET_COLOR);
32
 
33
         setFragmentShaderPart(theCtx, FragSection_GetColor, FragGetColor_RGB);
34
         if(!initProgram(theCtx)) {
35
@@ -311,6 +305,16 @@
36
 
37
 void StGLTextureButton::setTexturePath(const StString* theTexturesPaths,
38
                                        const size_t    theCount) {
39
+    if(myTextures.isNull()) {
40
+        if(theCount != 0) {
41
+            myTextures = new StGLTextureArray(theCount);
42
+        } else {
43
+        #ifdef ST_DEBUG
44
+            ST_DEBUG_LOG_AT("WARNING, Attempt to set an empty list of textures to StGLTextureButton!");
45
+        #endif
46
+            return;
47
+        }
48
+    }
49
     const size_t aNbTextures = (theCount > myTextures->size()) ? myTextures->size() : theCount;
50
 #ifdef ST_DEBUG
51
     if(theCount != myTextures->size()) {
52
@@ -369,6 +373,10 @@
53
 }
54
 
55
 bool StGLTextureButton::stglInit() {
56
+    if(myTextures.isNull()) {
57
+        return false;
58
+    }
59
+
60
     StGLContext& aCtx = getContext();
61
     const StHandle<StResourceManager>& aResMgr = getRoot()->getResourceManager();
62
     for(size_t aFaceIter = 0; aFaceIter < myTextures->size(); ++aFaceIter) {
63
@@ -403,7 +411,7 @@
64
         }
65
 
66
         GLint anInternalFormat = GL_RGB;
67
-        if(!StGLTexture::getInternalFormat(aCtx, anImage.getPlane(), anInternalFormat)) {
68
+        if(!StGLTexture::getInternalFormat(aCtx, anImage.getPlane().getFormat(), anInternalFormat)) {
69
             ST_ERROR_LOG("StGLTextureButton, texture '" + aTexture.getName() + "' has unsupported format!");
70
             continue;
71
         }
72
sview-17_04.tar.gz/StGLWidgets/StGLWidget.cpp -> sview-20_08.tar.gz/StGLWidgets/StGLWidget.cpp Changed
16
 
1
@@ -169,8 +169,12 @@
2
     return computeAbsolutePos(myParent->getRectPxAbsolute(), theRectPx, myCorner);
3
 }
4
 
5
-void StGLWidget::stglScissorRect(StGLBoxPx& theScissorRect) const {
6
-    myRoot->stglScissorRect(getRectPxAbsolute(), theScissorRect);
7
+void StGLWidget::stglScissorRect2d(StGLBoxPx& theScissorRect) const {
8
+    myRoot->stglScissorRect2d(getRectPxAbsolute(), theScissorRect);
9
+}
10
+
11
+void StGLWidget::stglScissorRect3d(StGLBoxPx& theScissorRect) const {
12
+    myRoot->stglScissorRect3d(getRectPxAbsolute(), theScissorRect);
13
 }
14
 
15
 StPointD_t StGLWidget::getPointGl(const StPointD_t& thePointZo) const {
16
sview-17_04.tar.gz/StGLWidgets/StGLWidgets.rc -> sview-20_08.tar.gz/StGLWidgets/StGLWidgets.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "OpenGL Widgets library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2009-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2009-2020 Kirill Gavrilov\000"
7
       VALUE "ProductName",     "StGLWidgets\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StImageViewer/StImageLoader.cpp -> sview-20_08.tar.gz/StImageViewer/StImageLoader.cpp Changed
387
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -21,12 +21,15 @@
9
 #include "StImageViewerStrings.h"
10
 #include "StImageViewerGUI.h"
11
 
12
+#include "../StMoviePlayer/StMoviePlayerInfo.h"
13
+
14
 #include <StAV/StAVImage.h>
15
 #include <StThreads/StThread.h>
16
 
17
 using namespace StImageViewerStrings;
18
 
19
 const char* StImageLoader::ST_IMAGES_MIME_STRING = ST_IMAGE_PLUGIN_MIME_CHAR;
20
+const char* StImageLoader::ST_VIDEOS_MIME_STRING = ST_VIDEO_PLUGIN_MIME_CHAR;
21
 
22
 namespace {
23
 
24
@@ -54,6 +57,7 @@
25
                              const StHandle<StGLTextureQueue>&  theTextureQueue,
26
                              const GLint                        theMaxTexDim)
27
 : myMimeList(ST_IMAGES_MIME_STRING),
28
+  myVideoMimeList(ST_VIDEOS_MIME_STRING),
29
   myResMgr(theResMgr),
30
   myLangMap(theLangMap),
31
   myPlayList(thePlayList),
32
@@ -64,9 +68,11 @@
33
   myMsgQueue(theMsgQueue),
34
   myImageLib(theImageLib),
35
   myAction(Action_NONE),
36
+  myIsTheaterMode(false),
37
   myToStickPano360(false),
38
   myToFlipCubeZ6x1(false),
39
-  myToFlipCubeZ3x2(false) {
40
+  myToFlipCubeZ3x2(false),
41
+  myToSwapJps(false) {
42
       myPlayList->setExtensions(myMimeList.getExtensionsList());
43
       myThread = new StThread(threadFunction, (void* )this, "StImageLoader");
44
 }
45
@@ -113,6 +119,7 @@
46
 }
47
 
48
 inline StHandle<StImage> scaledImage(StHandle<StImageFile>& theRef,
49
+                                     const StGLDeviceCaps&  theCaps,
50
                                      const size_t           theMaxSizeX,
51
                                      const size_t           theMaxSizeY,
52
                                      StCubemap              theCubemap,
53
@@ -122,7 +129,26 @@
54
         return theRef;
55
     }
56
 
57
-    if(theCubemap == StCubemap_Packed) {
58
+    const bool toConvertRgb = !theCaps.isSupportedFormat(theRef->getPlane().getFormat());
59
+    StImagePlane::ImgFormat anRgbImgFormat = StImagePlane::ImgRGB;
60
+    if(toConvertRgb) {
61
+        switch(theRef->getColorModel()) {
62
+            case StImage::ImgColor_RGB:
63
+                anRgbImgFormat = StImagePlane::ImgRGB;
64
+                break;
65
+            case StImage::ImgColor_RGBA:
66
+                anRgbImgFormat = StImagePlane::ImgRGBA;
67
+                break;
68
+            case StImage::ImgColor_GRAY:
69
+                anRgbImgFormat = StImagePlane::ImgGray;
70
+                break;
71
+            default:
72
+                anRgbImgFormat = StImagePlane::ImgRGB;
73
+                break;
74
+        }
75
+    }
76
+
77
+    if(theCubemap == StCubemap_Packed) { // skip scaling for StCubemap_PackedEAC
78
         size_t aSizesY[4] = {};
79
         bool toResize = false;
80
         size_t aMulX = (thePairRatio == StPairRatio_HalfWidth)  ? 2 : 1;
81
@@ -136,26 +162,48 @@
82
                 toResize = true;
83
             }
84
         }
85
-        if(!toResize) {
86
+        if(!toResize && !toConvertRgb) {
87
             return theRef;
88
         }
89
 
90
         StHandle<StImage> anImage = new StImage();
91
-        anImage->setColorModel(theRef->getColorModel());
92
-        anImage->setColorScale(theRef->getColorScale());
93
+        if(toConvertRgb) {
94
+            anImage->setColorModelPacked(anRgbImgFormat);
95
+            anImage->setColorScale(StImage::ImgScale_Full);
96
+        } else {
97
+            anImage->setColorModel(theRef->getColorModel());
98
+            anImage->setColorScale(theRef->getColorScale());
99
+        }
100
 
101
         double aRatioX = double(aSizesY[0] * theCubeCoeffs[0] * aMulX) / double(theRef->getSizeX());
102
         double aRatioY = double(aSizesY[0] * theCubeCoeffs[1] * aMulY) / double(theRef->getSizeY());
103
         anImage->setPixelRatio(float(double(theRef->getPixelRatio()) * aRatioY / aRatioX));
104
         for(size_t aPlaneId = 0; aPlaneId < 4; ++aPlaneId) {
105
+            if(toConvertRgb) {
106
+                if(aPlaneId != 0) {
107
+                    continue;
108
+                }
109
+                if(!anImage->changePlane(0).initTrash(anRgbImgFormat,
110
+                                                      aSizesY[0] * theCubeCoeffs[0] * aMulX,
111
+                                                      aSizesY[0] * theCubeCoeffs[1] * aMulY)) {
112
+                    ST_ERROR_LOG("Scale failed!");
113
+                    return theRef;
114
+                }
115
+                continue;
116
+            }
117
+
118
             const StImagePlane& aFromPlane = theRef->getPlane(aPlaneId);
119
             if(aFromPlane.isNull()) {
120
                 continue;
121
             }
122
 
123
+            size_t aPlanesSizeX = aSizesY[aPlaneId] * theCubeCoeffs[0] * aMulX;
124
+            size_t aSizeRowBytes = aPlanesSizeX * aFromPlane.getSizePixelBytes();
125
+            aSizeRowBytes = aSizeRowBytes + (32 - aSizeRowBytes % 32);
126
             if(!anImage->changePlane(aPlaneId).initTrash(aFromPlane.getFormat(),
127
                                                          aSizesY[aPlaneId] * theCubeCoeffs[0] * aMulX,
128
-                                                         aSizesY[aPlaneId] * theCubeCoeffs[1] * aMulY)) {
129
+                                                         aSizesY[aPlaneId] * theCubeCoeffs[1] * aMulY,
130
+                                                         aSizeRowBytes)) {
131
                 ST_ERROR_LOG("Scale failed!");
132
                 return theRef;
133
             }
134
@@ -170,17 +218,28 @@
135
     }
136
 
137
     if(theRef->getSizeX() <= theMaxSizeX
138
-    && theRef->getSizeY() <= theMaxSizeY) {
139
+    && theRef->getSizeY() <= theMaxSizeY
140
+    && !toConvertRgb) {
141
         return theRef;
142
     }
143
 
144
     StHandle<StImage> anImage = new StImage();
145
     const size_t aSizeX = stMin(theRef->getSizeX(), theMaxSizeX);
146
     const size_t aSizeY = stMin(theRef->getSizeY(), theMaxSizeY);
147
-    if(!anImage->initTrashLimited(*theRef, aSizeX, aSizeY)
148
-    || !StAVImage::resize(*theRef, *anImage)) {
149
-        ST_ERROR_LOG("Scale failed!");
150
-        return theRef;
151
+    if(toConvertRgb) {
152
+        anImage->setColorModelPacked(anRgbImgFormat);
153
+        anImage->setColorScale(StImage::ImgScale_Full);
154
+        if(!anImage->changePlane().initTrash(anRgbImgFormat, aSizeX, aSizeY)
155
+        || !StAVImage::resize(*theRef, *anImage)) {
156
+            ST_ERROR_LOG("Scale failed!");
157
+            return theRef;
158
+        }
159
+    } else {
160
+        if(!anImage->initTrashLimited(*theRef, aSizeX, aSizeY)
161
+        || !StAVImage::resize(*theRef, *anImage)) {
162
+            ST_ERROR_LOG("Scale failed!");
163
+            return theRef;
164
+        }
165
     }
166
     theRef->close();
167
     return anImage;
168
@@ -238,6 +297,7 @@
169
 
170
     StTimer aLoadTimer(true);
171
     StFormat  aSrcFormatCurr = myStFormatByUser;
172
+    StPanorama aSrcPanorama = StPanorama_OFF;
173
     if(anImgType == StImageFile::ST_TYPE_MPO
174
     || anImgType == StImageFile::ST_TYPE_JPEG
175
     || anImgType == StImageFile::ST_TYPE_JPS) {
176
@@ -286,6 +346,10 @@
177
             StDictEntry& anEntry  = anImgInfo->Info.addChange("Jpeg.JpsComment");
178
             anEntry.changeValue() = aParser.getJpsComment();
179
         }
180
+        if(!aParser.getXMP().isEmpty()) {
181
+            StDictEntry& anEntry  = anImgInfo->Info.addChange("Jpeg.XMP");
182
+            anEntry.changeValue() = aParser.getXMP();
183
+        }
184
         if(!anImg1.isNull()) {
185
             for(size_t anExifId = 0; anExifId < anImg1->Exif.size(); ++anExifId) {
186
                 metadataFromExif(anImg1->Exif[anExifId], anImgInfo);
187
@@ -300,6 +364,7 @@
188
         && aParser.getSrcFormat() != StFormat_AUTO) {
189
             aSrcFormatCurr = aParser.getSrcFormat();
190
         }
191
+        aSrcPanorama = aParser.getPanorama();
192
 
193
         //aParser.fillDictionary(anImgInfo->Info, true);
194
         if(!isParsed) {
195
@@ -360,6 +425,7 @@
196
             return false;
197
         }
198
         aRawFileL.freeBuffer();
199
+        aSrcPanorama = anImageFileL->getPanoramaFormat();
200
 
201
         StRawFile aRawFileR;
202
         if(StFileNode::isContentProtocolPath(aFilePathRight)) {
203
@@ -381,6 +447,7 @@
204
             return false;
205
         }
206
 
207
+        aSrcPanorama = anImageFileL->getPanoramaFormat();
208
         anImgInfo->StInfoStream = anImageFileL->getFormat();
209
         if(myStFormatByUser == StFormat_AUTO) {
210
             aSrcFormatCurr = anImgInfo->StInfoStream;
211
@@ -396,7 +463,7 @@
212
 
213
     // detect information from file name
214
     bool isAnamorphByName = false;
215
-    anImgInfo->StInfoFileName = st::formatFromName(aTitleString, isAnamorphByName);
216
+    anImgInfo->StInfoFileName = st::formatFromName(aTitleString, myToSwapJps, isAnamorphByName);
217
     if(aSrcFormatCurr == StFormat_AUTO
218
     && anImgInfo->StInfoFileName != StFormat_AUTO) {
219
         aSrcFormatCurr = anImgInfo->StInfoFileName;
220
@@ -429,27 +496,59 @@
221
         aSrcFormatCurr = StFormat_SeparateFrames;
222
     }
223
 
224
+    if(aSrcPanorama != StPanorama_OFF) {
225
+        theParams->ViewingMode = StStereoParams::getViewSurfaceForPanoramaSource(aSrcPanorama, true);
226
+    }
227
+    if(myIsTheaterMode && theParams->ViewingMode == StViewSurface_Plain) {
228
+        theParams->ViewingMode = StViewSurface_Theater;
229
+    } else if(!myIsTheaterMode && theParams->ViewingMode == StViewSurface_Theater) {
230
+        theParams->ViewingMode = StViewSurface_Plain;
231
+    }
232
+
233
     if(myToStickPano360
234
     && theParams->ViewingMode == StViewSurface_Plain) {
235
         StPanorama aPano = st::probePanorama(aSrcFormatCurr,
236
                                              theParams->Src1SizeX, theParams->Src1SizeY,
237
                                              theParams->Src2SizeX, theParams->Src2SizeY);
238
-        theParams->ViewingMode = (aPano == StPanorama_Cubemap6_1 || aPano == StPanorama_Cubemap3_2)
239
-                               ? StViewSurface_Cubemap
240
-                               : StViewSurface_Sphere;
241
+        theParams->ViewingMode = StStereoParams::getViewSurfaceForPanoramaSource(aPano, true);
242
+    }
243
+    StCubemap aSrcCubemap = StCubemap_OFF;
244
+    if(theParams->ViewingMode == StViewSurface_Cubemap) {
245
+        aSrcCubemap = StCubemap_Packed;
246
+    } else if(theParams->ViewingMode == StViewSurface_CubemapEAC) {
247
+        aSrcCubemap = StCubemap_PackedEAC;
248
     }
249
-    StCubemap aSrcCubemap = theParams->ViewingMode == StViewSurface_Cubemap ? StCubemap_Packed : StCubemap_OFF;
250
 
251
     size_t aCubeCoeffs[2] = {0, 0};
252
-    if(aSrcCubemap == StCubemap_Packed) {
253
+    if(aSrcCubemap == StCubemap_Packed
254
+    || aSrcCubemap == StCubemap_PackedEAC) {
255
         if(aSizeX1 / 6 == aSizeY1) {
256
             aCubeCoeffs[0] = 6;
257
             aCubeCoeffs[1] = 1;
258
             theParams->ToFlipCubeZ = myToFlipCubeZ6x1;
259
+        } else if(aSizeY1 / 6 == aSizeX1) {
260
+            aCubeCoeffs[0] = 1;
261
+            aCubeCoeffs[1] = 6;
262
+            theParams->ToFlipCubeZ = myToFlipCubeZ6x1;
263
         } else if(aSizeX1 / 3 == aSizeY1 / 2) {
264
             aCubeCoeffs[0] = 3;
265
             aCubeCoeffs[1] = 2;
266
             theParams->ToFlipCubeZ = myToFlipCubeZ3x2;
267
+        } else if(aSizeX1 / 2 == aSizeY1 / 3) {
268
+            aCubeCoeffs[0] = 2;
269
+            aCubeCoeffs[1] = 3;
270
+            theParams->ToFlipCubeZ = myToFlipCubeZ3x2;
271
+        } else if(aSrcCubemap == StCubemap_PackedEAC) {
272
+            // EAC on ytb is so cruel, that they don't use squared cube sides!
273
+            if(aSizeX1 > aSizeY1) {
274
+                aCubeCoeffs[0] = 3;
275
+                aCubeCoeffs[1] = 2;
276
+                theParams->ToFlipCubeZ = myToFlipCubeZ3x2;
277
+            } else {
278
+                aCubeCoeffs[0] = 2;
279
+                aCubeCoeffs[1] = 3;
280
+                theParams->ToFlipCubeZ = myToFlipCubeZ3x2;
281
+            }
282
         }
283
         if(!anImageFileR->isNull()
284
         && (aSizeX1 != aSizeX2 || aSizeY1 != aSizeY2)) {
285
@@ -466,8 +565,10 @@
286
         }
287
     }
288
 
289
-    StHandle<StImage> anImageL = scaledImage(anImageFileL, aSizeXLim, aSizeYLim, aSrcCubemap, aCubeCoeffs, aPairRatio);
290
-    StHandle<StImage> anImageR = scaledImage(anImageFileR, aSizeXLim, aSizeYLim, aSrcCubemap, aCubeCoeffs, aPairRatio);
291
+    StHandle<StImage> anImageL = scaledImage(anImageFileL, myTextureQueue->getDeviceCaps(), aSizeXLim, aSizeYLim,
292
+                                             aSrcCubemap, aCubeCoeffs, aPairRatio);
293
+    StHandle<StImage> anImageR = scaledImage(anImageFileR, myTextureQueue->getDeviceCaps(), aSizeXLim, aSizeYLim,
294
+                                             aSrcCubemap, aCubeCoeffs, aPairRatio);
295
 #ifdef ST_DEBUG
296
     const double aScaleTimeMSec = aLoadTimer.getElapsedTimeInMilliSec() - aLoadTimeMSec;
297
     if(anImageL != anImageFileL) {
298
@@ -503,27 +604,27 @@
299
         anImgInfo->Info.add(StArgument(tr(INFO_PIXEL_RATIO),
300
                                        StString(anImageFileL->getPixelRatio())));
301
     }
302
-    const StString aModelL = anImageFileL->formatImgColorModel();
303
+    const StString aFormatL = anImageFileL->formatImgPixelFormat();
304
     if(!anImageFileR->isNull()) {
305
         anImgInfo->Info.add(StArgument(tr(INFO_DIMENSIONS),
306
                                        formatSize(anImageL->getSizeX(), anImageL->getSizeY(),
307
                                                   theParams->Src1SizeX, theParams->Src1SizeY) + " " + tr(INFO_LEFT) + "\n"
308
                                      + formatSize(anImageR->getSizeX(), anImageR->getSizeY(),
309
                                                   theParams->Src2SizeX, theParams->Src2SizeY) + " " + tr(INFO_RIGHT)));
310
-        const StString aModelR = anImageFileR->formatImgColorModel();
311
-        if(aModelL == aModelR) {
312
-            anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL), aModelL));
313
+        const StString aFormatR = anImageFileR->formatImgPixelFormat();
314
+        if(aFormatL == aFormatR) {
315
+            anImgInfo->Info.add(StArgument(tr(INFO_PIXEL_FORMAT), aFormatL));
316
         } else {
317
-            anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL),
318
-                                aModelL + " " + tr(INFO_LEFT) + "\n"
319
-                              + aModelR + " " + tr(INFO_RIGHT)));
320
+            anImgInfo->Info.add(StArgument(tr(INFO_PIXEL_FORMAT),
321
+                                aFormatL + " " + tr(INFO_LEFT) + "\n"
322
+                              + aFormatR + " " + tr(INFO_RIGHT)));
323
         }
324
     } else {
325
         anImgInfo->Info.add(StArgument(tr(INFO_DIMENSIONS),
326
                                        formatSize(anImageL->getSizeX(), anImageL->getSizeY(),
327
                                                   theParams->Src1SizeX, theParams->Src1SizeY)));
328
-        anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL),
329
-                                       aModelL));
330
+        anImgInfo->Info.add(StArgument(tr(INFO_PIXEL_FORMAT),
331
+                                       aFormatL));
332
     }
333
     anImgInfo->Info.add(StArgument(tr(INFO_LOAD_TIME), StString(aLoadTimeMSec) + " " + tr(INFO_TIME_MSEC)));
334
     myLock.lock();
335
@@ -582,18 +683,18 @@
336
         aDataResult->initWrapper(aDataLeft);
337
     }
338
 
339
-    const StString& aTitle = myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_SNAPSHOT);
340
-    StMIMEList aFilter;
341
+    StOpenFileName anOpenInfo;
342
+    anOpenInfo.Title = myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_SNAPSHOT);
343
     StString aSaveExt;
344
     if(toSaveStereo) {
345
         switch(theImgType) {
346
             case StImageFile::ST_TYPE_PNG:
347
                 aSaveExt = ST_PNS_EXT;
348
-                aFilter.add(StMIME(ST_PNS_MIME, aSaveExt, ST_PNS_DESC));
349
+                anOpenInfo.Filter.add(StMIME(ST_PNS_MIME, aSaveExt, ST_PNS_DESC));
350
                 break;
351
             case StImageFile::ST_TYPE_JPEG:
352
                 aSaveExt = ST_JPS_EXT;
353
-                aFilter.add(StMIME(ST_JPS_MIME, aSaveExt, ST_JPS_DESC));
354
+                anOpenInfo.Filter.add(StMIME(ST_JPS_MIME, aSaveExt, ST_JPS_DESC));
355
                 break;
356
             default:
357
                 return false;
358
@@ -602,22 +703,22 @@
359
         switch(theImgType) {
360
             case StImageFile::ST_TYPE_PNG:
361
                 aSaveExt = ST_PNG_EXT;
362
-                aFilter.add(StMIME(ST_PNG_MIME, aSaveExt, ST_PNG_DESC));
363
+                anOpenInfo.Filter.add(StMIME(ST_PNG_MIME, aSaveExt, ST_PNG_DESC));
364
                 break;
365
             case StImageFile::ST_TYPE_JPEG:
366
                 aSaveExt = ST_JPG_EXT;
367
-                aFilter.add(StMIME(ST_JPG_MIME, aSaveExt, ST_JPEG_DESC));
368
+                anOpenInfo.Filter.add(StMIME(ST_JPG_MIME, aSaveExt, ST_JPEG_DESC));
369
                 break;
370
             default:
371
                 return false;
372
         }
373
     }
374
 
375
-    StString aFileNameSrc, aFolderSrc, aNameSrc, anExtSrc;
376
-    StFileNode::getFolderAndFile(theSource->getPath(), aFolderSrc, aFileNameSrc);
377
+    StString aFileNameSrc, aNameSrc, anExtSrc;
378
+    StFileNode::getFolderAndFile(theSource->getPath(), anOpenInfo.Folder, aFileNameSrc);
379
     StFileNode::getNameAndExtension(aFileNameSrc, aNameSrc, anExtSrc);
380
-    StString aFileToSave = (!aFolderSrc.isEmpty() ? aFolderSrc : "") + ST_FILE_SPLITTER + aNameSrc;
381
-    if(StFileNode::openFileDialog(aFolderSrc, aTitle, aFilter, aFileToSave, true)) {
382
+    StString aFileToSave = (!anOpenInfo.Folder.isEmpty() ? anOpenInfo.Folder : "") + ST_FILE_SPLITTER + aNameSrc;
383
+    if(StFileNode::openFileDialog(aFileToSave, anOpenInfo, true)) {
384
         if(StFileNode::getExtension(aFileToSave) != aSaveExt) {
385
             aFileToSave += StString('.') + aSaveExt;
386
         }
387
sview-17_04.tar.gz/StImageViewer/StImageLoader.h -> sview-20_08.tar.gz/StImageViewer/StImageLoader.h Changed
71
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -64,12 +64,13 @@
9
         public:
10
 
11
     static const char* ST_IMAGES_MIME_STRING;
12
+    static const char* ST_VIDEOS_MIME_STRING;
13
 
14
         public:
15
 
16
-    ST_LOCAL const StMIMEList& getMimeList() const {
17
-        return myMimeList;
18
-    }
19
+    ST_LOCAL const StMIMEList& getMimeListImages() const { return myMimeList; }
20
+
21
+    ST_LOCAL const StMIMEList& getMimeListVideo() const { return myVideoMimeList; }
22
 
23
     ST_LOCAL StImageLoader(const StImageFile::ImageClass      theImageLib,
24
                            const StHandle<StResourceManager>& theResMgr,
25
@@ -135,6 +136,13 @@
26
     ST_LOCAL void setCompressMemory(const bool theToCompress);
27
 
28
     /**
29
+     * Set theater mode.
30
+     */
31
+    ST_LOCAL void setTheaterMode(bool theIsTheater) {
32
+        myIsTheaterMode = theIsTheater;
33
+    }
34
+
35
+    /**
36
      * Stick to panorama 360 mode.
37
      */
38
     ST_LOCAL void setStickPano360(bool theToStick) {
39
@@ -155,6 +163,11 @@
40
         myToFlipCubeZ3x2 = theToFlip;
41
     }
42
 
43
+    /**
44
+     * Set if JPS file should be read as Left/Right (TRUE) of as Right/Left (FALSE).
45
+     */
46
+    ST_LOCAL void setSwapJPS(bool theToSwap) { myToSwapJps = theToSwap; }
47
+
48
         public:  //! @name Signals
49
 
50
     struct {
51
@@ -197,6 +210,7 @@
52
         private:
53
 
54
     const StMIMEList            myMimeList;
55
+    const StMIMEList            myVideoMimeList;
56
     StHandle<StThread>          myThread;        //!< main loop thread
57
     StHandle<StResourceManager> myResMgr;        //!< resource manager
58
     StHandle<StLangMap>         myLangMap;       //!< translations dictionary
59
@@ -212,9 +226,11 @@
60
 
61
     volatile StImageFile::ImageClass myImageLib;
62
     volatile Action            myAction;
63
+    volatile bool              myIsTheaterMode;  //!< flag indicating theater mode
64
     volatile bool              myToStickPano360; //!< stick to panorama 360 mode
65
     volatile bool              myToFlipCubeZ6x1; //!< flip Z within 6x1 cubemap input
66
     volatile bool              myToFlipCubeZ3x2; //!< flip Z within 3x2 cubemap input
67
+    volatile bool              myToSwapJps;      //!< read JPS as Left/Right instead of Right/Left
68
 
69
         private: //! @name no copies, please
70
 
71
sview-17_04.tar.gz/StImageViewer/StImageOpenDialog.cpp -> sview-20_08.tar.gz/StImageViewer/StImageOpenDialog.cpp Changed
33
 
1
@@ -91,19 +91,25 @@
2
 void StImageOpenDialog::dialogLoop() {
3
     myPathLeft .clear();
4
     myPathRight.clear();
5
-    StString aTitle = myPlugin->tr(myState == StImageOpenDialog::Dialog_ActiveDouble
6
+    StOpenFileName anOpenInfo;
7
+    anOpenInfo.Title = myPlugin->tr(myState == StImageOpenDialog::Dialog_ActiveDouble
8
                                  ? StImageViewerStrings::DIALOG_OPEN_LEFT
9
                                  : StImageViewerStrings::DIALOG_OPEN_FILE);
10
-
11
-    StString aDummy;
12
-    if(!StFileNode::openFileDialog(myFolder, aTitle, myPlugin->myLoader->getMimeList(), myPathLeft, false)) {
13
+    anOpenInfo.Folder = myFolder;
14
+    anOpenInfo.Filter = myPlugin->myLoader->getMimeListImages();
15
+    anOpenInfo.FilterTitle = "Image Files";
16
+    anOpenInfo.ExtraFilter = myPlugin->myLoader->getMimeListVideo();
17
+    anOpenInfo.ExtraFilterTitle = "Video Files";
18
+    if(!StFileNode::openFileDialog(myPathLeft, anOpenInfo, false)) {
19
         StMutexAuto aLock(myMutex);
20
         myState = StImageOpenDialog::Dialog_Inactive;
21
         return;
22
     } else if(myState == StImageOpenDialog::Dialog_ActiveDouble) {
23
-        aTitle = myPlugin->tr(StImageViewerStrings::DIALOG_OPEN_RIGHT);
24
+        anOpenInfo.Title = myPlugin->tr(StImageViewerStrings::DIALOG_OPEN_RIGHT);
25
+        StString aDummy;
26
         StFileNode::getFolderAndFile(myPathLeft, myFolder, aDummy);
27
-        if(!StFileNode::openFileDialog(myFolder, aTitle, myPlugin->myLoader->getMimeList(), myPathRight, false)) {
28
+        anOpenInfo.Folder = myFolder;
29
+        if(!StFileNode::openFileDialog(myPathRight, anOpenInfo, false)) {
30
             StMutexAuto aLock(myMutex);
31
             myState = StImageOpenDialog::Dialog_Inactive;
32
             return;
33
sview-17_04.tar.gz/StImageViewer/StImagePluginInfo.h -> sview-20_08.tar.gz/StImageViewer/StImagePluginInfo.h Changed
23
 
1
@@ -68,6 +68,13 @@
2
 #define ST_J2K_DESC "J2K - JPEG 2000 image, lossy"
3
 
4
 /**
5
+ *.insp - Insta360 Image (jpeg unstitched panorama)
6
+ */
7
+#define ST_INSP_MIME "image/x-insp"
8
+#define ST_INSP_EXT  "insp"
9
+#define ST_INSP_DESC "INSP - Insta360 Image (JPEG)"
10
+
11
+/**
12
  *.png - Portable Network Graphics image file, lossless
13
  */
14
 #define ST_PNG_MIME "image/x-png"
15
@@ -217,6 +224,7 @@
16
 ST_JPG_MIME ":" ST_JPG_EXT ":" ST_JPEG_DESC ";" \
17
 ST_JPE_MIME ":" ST_JPE_EXT ":" ST_JPEG_DESC ";" \
18
 ST_JPEG_MIME ":" ST_JPEG_EXT ":" ST_JPEG_DESC ";" \
19
+ST_INSP_MIME ":" ST_INSP_EXT ":" ST_INSP_DESC ";" \
20
 ST_JP2_MIME ":" ST_JP2_EXT ":" ST_JP2_DESC ";" \
21
 ST_J2K_MIME ":" ST_J2K_EXT ":" ST_J2K_DESC ";" \
22
 ST_PNG_MIME ":" ST_PNG_EXT ":" ST_PNG_DESC ";" \
23
sview-17_04.tar.gz/StImageViewer/StImageViewer.cpp -> sview-20_08.tar.gz/StImageViewer/StImageViewer.cpp Changed
417
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -50,7 +50,6 @@
9
 
10
 namespace {
11
 
12
-    static const char ST_SETTING_SLIDESHOW_DELAY[] = "slideShowDelay";
13
     static const char ST_SETTING_LAST_FOLDER[] = "lastFolder";
14
     static const char ST_SETTING_RECENT_L[]    = "recentL";
15
     static const char ST_SETTING_RECENT_R[]    = "recentR";
16
@@ -102,6 +101,7 @@
17
     params.SrcStereoFormat->setName(tr(MENU_MEDIA_SRC_FORMAT));
18
     params.ToShowPlayList->setName(tr(PLAYLIST));
19
     params.ToShowAdjustImage->setName(tr(MENU_VIEW_IMAGE_ADJUST));
20
+    params.ToSwapJPS->setName(tr(OPTION_SWAP_JPS));
21
     params.ToStickPanorama->setName(tr(MENU_VIEW_STICK_PANORAMA360));
22
     params.ToFlipCubeZ6x1->setName(tr(MENU_VIEW_FLIPZ_CUBE6x1));
23
     params.ToFlipCubeZ3x2->setName(tr(MENU_VIEW_FLIPZ_CUBE3x2));
24
@@ -109,9 +109,12 @@
25
     params.ToShowFps->setName(tr(MENU_SHOW_FPS));
26
     params.ToShowMenu->setName(stCString("Show main menu"));
27
     params.ToShowTopbar->setName(stCString("Show top toolbar"));
28
+    params.ToShowBottom->setName(stCString("Show bottom toolbar"));
29
+    params.SlideShowDelay->setName(stCString("Slideshow delay"));
30
     params.IsMobileUI->setName(stCString("Mobile UI"));
31
     params.ToHideStatusBar->setName("Hide system status bar");
32
     params.ToHideNavBar   ->setName(tr(OPTION_HIDE_NAVIGATION_BAR));
33
+    params.IsExclusiveFullScreen->setName(tr(MENU_EXCLUSIVE_FULLSCREEN));
34
     params.IsVSyncOn->setName(tr(MENU_VSYNC));
35
     params.ToOpenLast->setName(tr(OPTION_OPEN_LAST_ON_STARTUP));
36
     params.ToSaveRecent->setName(stCString("Remember recent file"));
37
@@ -129,7 +132,6 @@
38
   myEventLoaded(false),
39
   //
40
   mySlideShowTimer(false),
41
-  mySlideShowDelay(4.0),
42
   //
43
   myToCheckUpdates(true),
44
   myToSaveSrcFormat(false),
45
@@ -166,6 +168,8 @@
46
     params.ToShowPlayList->signals.onChanged = stSlot(this, &StImageViewer::doShowPlayList);
47
     params.ToShowAdjustImage = new StBoolParamNamed(false, stCString("showAdjustImage"));
48
     params.ToShowAdjustImage->signals.onChanged = stSlot(this, &StImageViewer::doShowAdjustImage);
49
+    params.ToSwapJPS = new StBoolParamNamed(false, stCString("toSwapJPS"));
50
+    params.ToSwapJPS->signals.onChanged = stSlot(this, &StImageViewer::doChangeSwapJPS);
51
     params.ToStickPanorama = new StBoolParamNamed(false, stCString("toStickPano360"));
52
     params.ToStickPanorama->signals.onChanged = stSlot(this, &StImageViewer::doChangeStickPano360);
53
     params.ToFlipCubeZ6x1= new StBoolParamNamed(true,  stCString("toFlipCube6x1"));
54
@@ -176,6 +180,13 @@
55
     params.ToShowFps     = new StBoolParamNamed(false, stCString("toShowFps"));
56
     params.ToShowMenu    = new StBoolParamNamed(true,  stCString("toShowMenu"));
57
     params.ToShowTopbar  = new StBoolParamNamed(true,  stCString("toShowTopbar"));
58
+    params.ToShowBottom  = new StBoolParamNamed(true,  stCString("toShowBottom"));
59
+    params.SlideShowDelay = new StFloat32Param(4.0f, stCString("slideShowDelay2"));
60
+    params.SlideShowDelay->setMinMaxValues(1.0f, 10.0f);
61
+    params.SlideShowDelay->setDefValue(4.0f);
62
+    params.SlideShowDelay->setStep(1.0f);
63
+    params.SlideShowDelay->setTolerance(0.1f);
64
+    params.SlideShowDelay->setFormat(stCString("%01.1f s"));
65
     params.IsMobileUI    = new StBoolParamNamed(StWindow::isMobile(), stCString("isMobileUI"));
66
     params.IsMobileUI->signals.onChanged = stSlot(this, &StImageViewer::doChangeMobileUI);
67
     params.IsMobileUISwitch = new StBoolParam(params.IsMobileUI->getValue());
68
@@ -184,6 +195,7 @@
69
     params.ToHideStatusBar->signals.onChanged = stSlot(this, &StImageViewer::doHideSystemBars);
70
     params.ToHideNavBar    = new StBoolParamNamed(true, stCString("toHideNavBar"));
71
     params.ToHideNavBar   ->signals.onChanged = stSlot(this, &StImageViewer::doHideSystemBars);
72
+    params.IsExclusiveFullScreen = new StBoolParamNamed(false, stCString("isExclusiveFullScreen"));
73
     params.IsVSyncOn     = new StBoolParamNamed(true,  stCString("vsync"));
74
     params.IsVSyncOn->signals.onChanged = stSlot(this, &StImageViewer::doSwitchVSync);
75
     StApplication::params.VSyncMode->setValue(StGLContext::VSync_ON);
76
@@ -202,23 +214,22 @@
77
     mySettings->loadString(ST_SETTING_LAST_FOLDER,        params.lastFolder);
78
     mySettings->loadParam (params.LastUpdateDay);
79
     mySettings->loadParam (params.CheckUpdatesDays);
80
+    mySettings->loadParam (params.ToSwapJPS);
81
     mySettings->loadParam (params.ToStickPanorama);
82
     mySettings->loadParam (params.ToFlipCubeZ6x1);
83
     mySettings->loadParam (params.ToFlipCubeZ3x2);
84
     myToCheckPoorOrient = !mySettings->loadParam(params.ToTrackHead);
85
     mySettings->loadParam (params.ToShowFps);
86
+    mySettings->loadParam (params.SlideShowDelay);
87
     mySettings->loadParam (params.IsMobileUI);
88
     mySettings->loadParam (params.ToHideStatusBar);
89
     mySettings->loadParam (params.ToHideNavBar);
90
     mySettings->loadParam (params.ToOpenLast);
91
+    mySettings->loadParam (params.IsExclusiveFullScreen);
92
     mySettings->loadParam (params.IsVSyncOn);
93
     mySettings->loadParam (params.ToShowPlayList);
94
     mySettings->loadParam (params.ToShowAdjustImage);
95
 
96
-    int32_t aSlideShowDelayInt = int32_t(mySlideShowDelay);
97
-    mySettings->loadInt32 (ST_SETTING_SLIDESHOW_DELAY,    aSlideShowDelayInt);
98
-    mySlideShowDelay = double(aSlideShowDelayInt);
99
-
100
 #if defined(__ANDROID__)
101
     addRenderer(new StOutInterlace  (myResMgr, theParentWin));
102
     addRenderer(new StOutAnaglyph   (myResMgr, theParentWin));
103
@@ -251,6 +262,9 @@
104
     anAction = new StActionBool(stCString("DoShowFPS"), params.ToShowFps);
105
     addAction(Action_ShowFps, anAction, ST_VK_F12);
106
 
107
+    anAction = new StActionIntSlot(stCString("DoShowGUI"), stSlot(this, &StImageViewer::doShowHideGUI), 0);
108
+    addAction(Action_ShowGUI, anAction, ST_VK_TILDE);
109
+
110
     anAction = new StActionIntValue(stCString("DoSrcAuto"), params.SrcStereoFormat, StFormat_AUTO);
111
     addAction(Action_SrcAuto, anAction, ST_VK_A);
112
 
113
@@ -276,10 +290,10 @@
114
     addAction(Action_ListLast, anAction, ST_VK_END);
115
 
116
     anAction = new StActionIntSlot(stCString("DoListPrev"), stSlot(this, &StImageViewer::doListPrev), 0);
117
-    addAction(Action_ListPrev, anAction, ST_VK_PRIOR);
118
+    addAction(Action_ListPrev, anAction, ST_VK_PRIOR, StWindow::isMobile() ? ST_VK_VOLUME_UP : 0);
119
 
120
     anAction = new StActionIntSlot(stCString("DoListNext"), stSlot(this, &StImageViewer::doListNext), 0);
121
-    addAction(Action_ListNext, anAction, ST_VK_NEXT);
122
+    addAction(Action_ListNext, anAction, ST_VK_NEXT,  StWindow::isMobile() ? ST_VK_VOLUME_DOWN : 0);
123
 
124
     anAction = new StActionIntSlot(stCString("DoSlideShow"), stSlot(this, &StImageViewer::doSlideShow), 0);
125
     addAction(Action_SlideShow, anAction, ST_VK_SPACE);
126
@@ -302,6 +316,23 @@
127
 
128
     anAction = new StActionIntSlot(stCString("DoPanoramaOnOff"), stSlot(this, &StImageViewer::doPanoramaOnOff), 0);
129
     addAction(Action_PanoramaOnOff, anAction, ST_VK_P);
130
+
131
+    {
132
+    anAction = new StActionIntSlot(stCString("DoOutStereoNormal"), stSlot(this, &StImageViewer::doSetStereoOutput), StGLImageRegion::MODE_STEREO);
133
+    addAction(Action_OutStereoNormal, anAction);
134
+
135
+    anAction = new StActionIntSlot(stCString("DoOutStereoLeftView"), stSlot(this, &StImageViewer::doSetStereoOutput), StGLImageRegion::MODE_ONLY_LEFT);
136
+    addAction(Action_OutStereoLeftView, anAction);
137
+
138
+    anAction = new StActionIntSlot(stCString("DoOutStereoRightView"), stSlot(this, &StImageViewer::doSetStereoOutput), StGLImageRegion::MODE_ONLY_RIGHT);
139
+    addAction(Action_OutStereoRightView, anAction);
140
+
141
+    anAction = new StActionIntSlot(stCString("DoOutStereoParallelPair"), stSlot(this, &StImageViewer::doSetStereoOutput), StGLImageRegion::MODE_PARALLEL);
142
+    addAction(Action_OutStereoParallelPair, anAction);
143
+
144
+    anAction = new StActionIntSlot(stCString("DoOutStereoCrossEyed"), stSlot(this, &StImageViewer::doSetStereoOutput), StGLImageRegion::MODE_CROSSYED);
145
+    addAction(Action_OutStereoCrossEyed, anAction);
146
+    }
147
 }
148
 
149
 bool StImageViewer::resetDevice() {
150
@@ -341,19 +372,21 @@
151
         mySettings->saveParam (params.ScaleAdjust);
152
         mySettings->saveParam (params.ScaleHiDPI2X);
153
         mySettings->saveParam (params.TargetFps);
154
-        mySettings->saveInt32(ST_SETTING_SLIDESHOW_DELAY, int(mySlideShowDelay));
155
         mySettings->saveParam(params.LastUpdateDay);
156
         mySettings->saveParam(params.CheckUpdatesDays);
157
         mySettings->saveString(ST_SETTING_IMAGELIB,  StImageFile::imgLibToString(params.imageLib));
158
+        mySettings->saveParam (params.ToSwapJPS);
159
         mySettings->saveParam (params.ToStickPanorama);
160
         mySettings->saveParam (params.ToFlipCubeZ6x1);
161
         mySettings->saveParam (params.ToFlipCubeZ3x2);
162
         mySettings->saveParam (params.ToTrackHead);
163
         mySettings->saveParam (params.ToShowFps);
164
+        mySettings->saveParam (params.SlideShowDelay);
165
         mySettings->saveParam (params.IsMobileUI);
166
         mySettings->saveParam (params.ToHideStatusBar);
167
         mySettings->saveParam (params.ToHideNavBar);
168
         mySettings->saveParam (params.ToOpenLast);
169
+        mySettings->saveParam (params.IsExclusiveFullScreen);
170
         mySettings->saveParam (params.IsVSyncOn);
171
         mySettings->saveParam (params.ToShowPlayList);
172
         mySettings->saveParam (params.ToShowAdjustImage);
173
@@ -446,6 +479,12 @@
174
         return false;
175
     }
176
     myGUI->stglInit();
177
+    StRectF_t aFrustL, aFrustR;
178
+    if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
179
+        myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
180
+    } else {
181
+        myGUI->changeCamera()->resetCustomProjection();
182
+    }
183
     myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
184
 
185
     for(size_t anIter = 0; anIter < myGUI->myImage->getActions().size(); ++anIter) {
186
@@ -511,6 +550,7 @@
187
                                  myGUI->myImage->getTextureQueue(), myContext->getMaxTextureSize());
188
     myLoader->signals.onLoaded.connect(this, &StImageViewer::doLoaded);
189
     myLoader->setCompressMemory(myWindow->isMobile());
190
+    myLoader->setSwapJPS(params.ToSwapJPS->getValue());
191
     myLoader->setStickPano360(params.ToStickPanorama->getValue());
192
     myLoader->setFlipCubeZ6x1(params.ToFlipCubeZ6x1->getValue());
193
     myLoader->setFlipCubeZ3x2(params.ToFlipCubeZ3x2->getValue());
194
@@ -518,7 +558,7 @@
195
     // load this parameter AFTER image thread creation
196
     mySettings->loadParam(params.SrcStereoFormat);
197
 
198
-#if !defined(ST_NO_UPDATES_CHECK)
199
+#if defined(ST_UPDATES_CHECK)
200
     // read the current time
201
     time_t aRawtime;
202
     time(&aRawtime);
203
@@ -723,6 +763,12 @@
204
     if(toMobileGui != wasMobileGui) {
205
         doChangeMobileUI(params.IsMobileUI->getValue());
206
     } else {
207
+        StRectF_t aFrustL, aFrustR;
208
+        if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
209
+            myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
210
+        } else {
211
+            myGUI->changeCamera()->resetCustomProjection();
212
+        }
213
         myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
214
     }
215
 }
216
@@ -789,7 +835,9 @@
217
         return;
218
     }
219
 
220
+    const bool isReadOnly = StFileNode::isFileReadOnly(myFileToDelete->getPath());
221
     const StString aText = myLangMap->getValue(StImageViewerStrings::DIALOG_DELETE_FILE_QUESTION)
222
+                         + (isReadOnly ? "\nWARNING! The file is READ ONLY!" : "")
223
                          + "\n" + myFileToDelete->getPath();
224
 
225
     StGLMessageBox* aDialog = new StGLMessageBox(myGUI.access(), myLangMap->getValue(StImageViewerStrings::DIALOG_DELETE_FILE_TITLE),
226
@@ -805,6 +853,7 @@
227
         return;
228
     }
229
 
230
+    StFileNode::removeReadOnlyFlag(myFileToDelete->getPath());
231
     myPlayList->removePhysically(myFileToDelete);
232
     if(!myPlayList->isEmpty()) {
233
         doUpdateStateLoading();
234
@@ -918,20 +967,8 @@
235
 }
236
 
237
 void StImageViewer::doGesture(const StGestureEvent& theEvent) {
238
-    if(myGUI.isNull()
239
-    || myGUI->myImage == NULL) {
240
-        return;
241
-    }
242
-
243
-    for(StGLWidget *aChildIter(myGUI->getChildren()->getLast()), *aChildActive(NULL); aChildIter != NULL;) {
244
-        aChildActive = aChildIter;
245
-        aChildIter   = aChildIter->getPrev();
246
-        if(aChildActive->isVisibleAndPointIn(myGUI->getCursorZo())) {
247
-            if(aChildActive == myGUI->myImage) {
248
-                myGUI->myImage->doGesture(theEvent);
249
-            }
250
-            break;
251
-        }
252
+    if(!myGUI.isNull()) {
253
+        myGUI->doGesture(theEvent);
254
     }
255
 }
256
 
257
@@ -954,9 +991,19 @@
258
     }
259
 
260
     const StString aFile1 = theEvent.Files[0];
261
-    /*if(!myPlayList->checkExtension(aFile1)) {
262
+    if(!myPlayList->checkExtension(aFile1)
263
+     && myLoader->getMimeListVideo().checkExtension(StFileNode::getExtension(aFile1))) {
264
+        // redirect to StMoviePlayer
265
+        myOpenFileOtherApp = new StOpenInfo();
266
+        StArgumentsMap anArgs;
267
+        anArgs.add(StArgument("in", "video"));
268
+        myOpenFileOtherApp->setArgumentsMap(anArgs);
269
+        myOpenFileOtherApp->setPath(aFile1);
270
+        exit(0);
271
         return;
272
-    } else */if(theEvent.NbFiles == 1) {
273
+    }
274
+
275
+    if(theEvent.NbFiles == 1) {
276
         myPlayList->open(aFile1);
277
         doUpdateStateLoading();
278
         myLoader->doLoadNext();
279
@@ -1002,7 +1049,18 @@
280
             myPlayList->clear();
281
             myPlayList->addOneFile(myOpenDialog->getPathLeft(), myOpenDialog->getPathRight());
282
         } else {
283
-            myPlayList->open(myOpenDialog->getPathLeft());
284
+            if(!myPlayList->checkExtension(myOpenDialog->getPathLeft())
285
+             && myLoader->getMimeListVideo().checkExtension(StFileNode::getExtension(myOpenDialog->getPathLeft()))) {
286
+                // redirect to StMoviePlayer
287
+                myOpenFileOtherApp = new StOpenInfo();
288
+                StArgumentsMap anArgs;
289
+                anArgs.add(StArgument("in", "video"));
290
+                myOpenFileOtherApp->setArgumentsMap(anArgs);
291
+                myOpenFileOtherApp->setPath(myOpenDialog->getPathLeft());
292
+                exit(0);
293
+            } else {
294
+                myPlayList->open(myOpenDialog->getPathLeft());
295
+            }
296
         }
297
 
298
         doUpdateStateLoading();
299
@@ -1024,7 +1082,7 @@
300
         myLoader->doLoadNext();
301
     }
302
 
303
-    if(mySlideShowTimer.getElapsedTimeInSec() > mySlideShowDelay) {
304
+    if(mySlideShowTimer.getElapsedTimeInSec() > params.SlideShowDelay->getValue()) {
305
         mySlideShowTimer.restart();
306
         doListNext();
307
     }
308
@@ -1044,6 +1102,9 @@
309
     myGUI->setVisibility(myWindow->getMousePos(), myToHideUIFullScr && isFullScreen);
310
     bool toHideCursor = isFullScreen && myGUI->toHideCursor();
311
     myWindow->showCursor(!toHideCursor);
312
+
313
+    // for image viewer it is OK to make longer smoothed uploads
314
+    myGUI->myImage->getTextureQueue()->getUploadParams().MaxUploadIterations = 10;
315
 }
316
 
317
 void StImageViewer::stglDraw(unsigned int theView) {
318
@@ -1145,12 +1206,14 @@
319
         return;
320
     }
321
 
322
+    myLoader->setTheaterMode(theMode == StViewSurface_Theater);
323
+
324
     bool isChanged = false;
325
     StGLFrameTextures& aTexture = myGUI->myImage->getTextureQueue()->getQTexture().getFront(StGLQuadTexture::LEFT_TEXTURE);
326
     if(aTexture.getPlane(0).getTarget() == GL_TEXTURE_CUBE_MAP) {
327
-        isChanged = (theMode != StViewSurface_Cubemap);
328
+        isChanged = (theMode != StViewSurface_Cubemap && theMode != StViewSurface_CubemapEAC);
329
     } else {
330
-        isChanged = (theMode == StViewSurface_Cubemap);
331
+        isChanged = (theMode == StViewSurface_Cubemap || theMode == StViewSurface_CubemapEAC);
332
     }
333
 
334
     if(isChanged
335
@@ -1159,6 +1222,13 @@
336
     }
337
 }
338
 
339
+void StImageViewer::doSetStereoOutput(const size_t theMode) {
340
+    if(myLoader.isNull()) {
341
+        return;
342
+    }
343
+    myGUI->myImage->params.DisplayMode->setValue((int32_t )theMode);
344
+}
345
+
346
 void StImageViewer::doPanoramaOnOff(const size_t ) {
347
     if(myLoader.isNull()) {
348
         return;
349
@@ -1180,9 +1250,39 @@
350
     StPanorama aPano = st::probePanorama(aParams->StereoFormat,
351
                                          aParams->Src1SizeX, aParams->Src1SizeY,
352
                                          aParams->Src2SizeX, aParams->Src2SizeY);
353
-    myGUI->myImage->params.ViewMode->setValue(aPano == StPanorama_Cubemap6_1 || aPano == StPanorama_Cubemap3_2
354
-                                            ? StViewSurface_Cubemap
355
-                                            : StViewSurface_Sphere);
356
+    if(aPano == StPanorama_OFF) {
357
+        size_t aSizeX = aParams->Src1SizeX;
358
+        size_t aSizeY = aParams->Src1SizeY;
359
+        StPairRatio aPairRatio = st::formatToPairRatio(aParams->StereoFormat);
360
+        if(aPairRatio == StPairRatio_HalfWidth) {
361
+            aSizeX /= 2;
362
+        } else if(aPairRatio == StPairRatio_HalfHeight) {
363
+            aSizeY /= 2;
364
+        }
365
+        if(aSizeX > 8 && aSizeY > 8) {
366
+            if(double(aSizeX)/double(aSizeY) > 3.5) {
367
+                myGUI->myImage->params.ViewMode->setValue(StViewSurface_Cylinder);
368
+                return;
369
+            }
370
+        }
371
+    }
372
+    myGUI->myImage->params.ViewMode->setValue(StStereoParams::getViewSurfaceForPanoramaSource(aPano, true));
373
+}
374
+
375
+void StImageViewer::doChangeSwapJPS(const bool ) {
376
+    if(!myLoader.isNull()) {
377
+        myLoader->setSwapJPS(params.ToSwapJPS->getValue());
378
+        StHandle<StStereoParams> aParams = myGUI->myImage->getSource();
379
+        if(!aParams.isNull()
380
+        && !myPlayList->isEmpty()) {
381
+            StString aCurrFile = myPlayList->getCurrentTitle();
382
+            aCurrFile.toLowerCase();
383
+            if(aCurrFile.isEndsWith(stCString(".jps"))
384
+            || aCurrFile.isEndsWith(stCString(".pps"))) {
385
+                myLoader->doLoadNext();
386
+            }
387
+        }
388
+    }
389
 }
390
 
391
 void StImageViewer::doChangeStickPano360(const bool ) {
392
@@ -1283,6 +1383,16 @@
393
     }
394
 }
395
 
396
+void StImageViewer::doShowHideGUI(const size_t ) {
397
+    const bool toShow = !params.ToShowMenu->getValue() || (!myGUI.isNull() && !myGUI->isVisibleGUI());
398
+    params.ToShowMenu->setValue(toShow);
399
+    params.ToShowTopbar->setValue(toShow);
400
+    params.ToShowBottom->setValue(toShow);
401
+    if(toShow && !myGUI.isNull()) {
402
+        myGUI->setVisibility(myWindow->getMousePos(), false, true);
403
+    }
404
+}
405
+
406
 void StImageViewer::doSlideShow(const size_t ) {
407
     if(mySlideShowTimer.getElapsedTimeInSec() > 0.0) {
408
         mySlideShowTimer.stop();
409
@@ -1310,6 +1420,7 @@
410
 
411
 void StImageViewer::doFullscreen(const bool theIsFullscreen) {
412
     if(!myWindow.isNull()) {
413
+        myWindow->setAttribute(StWinAttr_ExclusiveFullScreen, params.IsExclusiveFullScreen->getValue());
414
         myWindow->setFullScreen(theIsFullscreen);
415
     }
416
 }
417
sview-17_04.tar.gz/StImageViewer/StImageViewer.h -> sview-20_08.tar.gz/StImageViewer/StImageViewer.h Changed
83
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -73,7 +73,7 @@
9
     /**
10
      * Reset device - release GL resources in old window and re-create them in new window.
11
      */
12
-    ST_CPPEXPORT virtual bool resetDevice();
13
+    ST_CPPEXPORT virtual bool resetDevice() ST_ATTR_OVERRIDE;
14
 
15
         private: //! @name window events slots
16
 
17
@@ -105,6 +105,7 @@
18
     ST_LOCAL void doListLast(const size_t dummy = 0);
19
     ST_LOCAL void doDeleteFileBegin(const size_t dummy = 0);
20
     ST_LOCAL void doDeleteFileEnd(const size_t dummy = 0);
21
+    ST_LOCAL void doShowHideGUI(const size_t dummy = 0);
22
     ST_LOCAL void doSlideShow(const size_t dummy = 0);
23
     ST_LOCAL void doQuit(const size_t dummy = 0);
24
 
25
@@ -131,19 +132,23 @@
26
         StHandle<StEnumParam>         CheckUpdatesDays; //!< days count between updates checks
27
         StHandle<StInt32ParamNamed>   LastUpdateDay;    //!< the last time update has been checked
28
         StHandle<StInt32ParamNamed>   SrcStereoFormat;  //!< source format
29
+        StHandle<StBoolParamNamed>    ToSwapJPS;        //!< swap JPS views order
30
         StHandle<StBoolParamNamed>    ToStickPanorama;  //!< force panorama input for all files
31
         StHandle<StBoolParamNamed>    ToFlipCubeZ6x1;   //!< flip Z coordinate within Cube map 6x1
32
         StHandle<StBoolParamNamed>    ToFlipCubeZ3x2;   //!< flip Z coordinate within Cube map 3x2
33
         StHandle<StBoolParamNamed>    ToTrackHead;      //!< enable/disable head-tracking
34
         StHandle<StBoolParamNamed>    ToShowMenu;       //!< show main menu
35
         StHandle<StBoolParamNamed>    ToShowTopbar;     //!< show topbar
36
+        StHandle<StBoolParamNamed>    ToShowBottom;     //!< show bottom
37
         StHandle<StBoolParamNamed>    ToShowPlayList;   //!< display playlist
38
         StHandle<StBoolParamNamed>    ToShowAdjustImage;//!< display image adjustment overlay
39
         StHandle<StBoolParamNamed>    ToShowFps;        //!< display FPS meter
40
+        StHandle<StFloat32Param>      SlideShowDelay;   //!< slideshow delay
41
         StHandle<StBoolParamNamed>    IsMobileUI;       //!< display mobile interface (user option)
42
         StHandle<StBoolParam>         IsMobileUISwitch; //!< display mobile interface (actual value)
43
         StHandle<StBoolParamNamed>    ToHideStatusBar;  //!< hide system-provided status bar
44
         StHandle<StBoolParamNamed>    ToHideNavBar;     //!< hide system-provided navigation bar
45
+        StHandle<StBoolParamNamed>    IsExclusiveFullScreen; //!< exclusive fullscreen mode
46
         StHandle<StBoolParamNamed>    IsVSyncOn;        //!< flag to use VSync
47
         StHandle<StBoolParamNamed>    ToOpenLast;       //!< option to open last file from recent list by default
48
         StHandle<StBoolParamNamed>    ToSaveRecent;     //!< load/save recent file
49
@@ -186,7 +191,9 @@
50
     ST_LOCAL void doFullscreen(const bool theIsFullscreen);
51
     ST_LOCAL void doSwitchSrcFormat(const int32_t theSrcFormat);
52
     ST_LOCAL void doSwitchViewMode(const int32_t theMode);
53
+    ST_LOCAL void doSetStereoOutput(const size_t theMode);
54
     ST_LOCAL void doPanoramaOnOff(const size_t );
55
+    ST_LOCAL void doChangeSwapJPS(const bool );
56
     ST_LOCAL void doChangeStickPano360(const bool );
57
     ST_LOCAL void doChangeFlipCubeZ(const bool );
58
     ST_LOCAL void doShowPlayList(const bool theToShow);
59
@@ -219,6 +226,12 @@
60
         Action_StereoParamsBegin,
61
         Action_StereoParamsEnd = Action_StereoParamsBegin + StGLImageRegion::ActionsNb - 1,
62
         Action_PanoramaOnOff,
63
+        Action_ShowGUI,
64
+        Action_OutStereoNormal,
65
+        Action_OutStereoLeftView,
66
+        Action_OutStereoRightView,
67
+        Action_OutStereoParallelPair,
68
+        Action_OutStereoCrossEyed,
69
     };
70
 
71
         private:
72
@@ -257,9 +270,7 @@
73
 
74
     StCondition                 myEventLoaded;     //!< indicate that new file was open
75
     StTimer                     myInactivityTimer; //!< timer initialized when application goes into paused state
76
-
77
-    StTimer                     mySlideShowTimer;  //!< slideshow stuff
78
-    double                      mySlideShowDelay;
79
+    StTimer                     mySlideShowTimer;  //!< slideshow timer
80
 
81
     bool                        myToCheckUpdates;
82
     bool                        myToSaveSrcFormat; //!< indicates that active source format should be saved or not
83
sview-17_04.tar.gz/StImageViewer/StImageViewer.rc -> sview-20_08.tar.gz/StImageViewer/StImageViewer.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereoscopic Image Viewer\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StImageViewer\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StImageViewer/StImageViewerGUI.cpp -> sview-20_08.tar.gz/StImageViewer/StImageViewerGUI.cpp Changed
363
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -56,6 +56,8 @@
9
 
10
 namespace {
11
 
12
+    static const float THE_VISIBILITY_IDLE_TIME = 2.0f;
13
+
14
     static const int DISPL_Y_REGION_UPPER = 32;
15
     static const int DISPL_X_REGION_UPPER = 32;
16
 
17
@@ -135,34 +137,34 @@
18
     const int      anIconStep = scale(48);
19
     aButtonMargins.extend(scale(8));
20
 
21
-    myPanelUpper = new StGLContainer(this, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), scale(4096), scale(128));
22
+    myPanelUpper = new StGLContainer(this, aLeft, aTop, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), scale(4096), scale(128));
23
 
24
     // append textured buttons
25
-    myBtnOpen   = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
26
+    myBtnOpen   = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
27
     myBtnOpen->signals.onBtnClick.connect(myPlugin, &StImageViewer::doOpen1FileAction);
28
     myBtnOpen->setTexturePath(iconTexture(stCString("actionOpen"), anIconSize));
29
     myBtnOpen->setDrawShadow(true);
30
     myBtnOpen->changeMargins() = aButtonMargins;
31
 
32
-    myBtnPrev   = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
33
+    myBtnPrev   = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
34
     myBtnPrev->signals.onBtnClick.connect(myPlugin, &StImageViewer::doListPrev);
35
     myBtnPrev->setTexturePath(iconTexture(stCString("actionBack"), anIconSize));
36
     myBtnPrev->setDrawShadow(true);
37
     myBtnPrev->changeMargins() = aButtonMargins;
38
 
39
-    myBtnNext   = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
40
+    myBtnNext   = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
41
     myBtnNext->signals.onBtnClick.connect(myPlugin, &StImageViewer::doListNext);
42
     myBtnNext->setTexturePath(iconTexture(stCString("actionNext"), anIconSize));
43
     myBtnNext->setDrawShadow(true);
44
     myBtnNext->changeMargins() = aButtonMargins;
45
 
46
-    myBtnInfo = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
47
+    myBtnInfo = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
48
     myBtnInfo->signals.onBtnClick += stSlot(myPlugin, &StImageViewer::doAboutImage);
49
     myBtnInfo->setTexturePath(iconTexture(stCString("actionInfo"),  anIconSize));
50
     myBtnInfo->setDrawShadow(true);
51
     myBtnInfo->changeMargins() = aButtonMargins;
52
 
53
-    StGLTextureButton* aSrcBtn = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop,
54
+    StGLTextureButton* aSrcBtn = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0,
55
                                                        StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), StFormat_NB);
56
     aSrcBtn->changeMargins() = aButtonMargins;
57
     aSrcBtn->signals.onBtnClick += stSlot(this, &StImageViewerGUI::doDisplayStereoFormatCombo);
58
@@ -188,7 +190,7 @@
59
     myBtnSwapLR = new StGLCheckboxTextured(myPanelUpper, myImage->params.SwapLR,
60
                                            iconTexture(stCString("actionSwapLROff"), anIconSize),
61
                                            iconTexture(stCString("actionSwapLROn"),  anIconSize),
62
-                                           aLeft + (aBtnIter++) * anIconStep, aTop,
63
+                                           (aBtnIter++) * anIconStep, 0,
64
                                            StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
65
     myBtnSwapLR->setDrawShadow(true);
66
     myBtnSwapLR->changeMargins() = aButtonMargins;
67
@@ -197,7 +199,7 @@
68
     myBtnPanorama = new StGLCheckboxTextured(myPanelUpper, aTrackedPano,
69
                                              iconTexture(stCString("actionPanoramaOff"), anIconSize),
70
                                              iconTexture(stCString("actionPanorama"),    anIconSize),
71
-                                             aLeft + (aBtnIter++) * anIconStep, aTop,
72
+                                             (aBtnIter++) * anIconStep, 0,
73
                                              StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
74
     myBtnPanorama->signals.onBtnClick += stSlot(this, &StImageViewerGUI::doPanoramaCombo);
75
     myBtnPanorama->setDrawShadow(true);
76
@@ -206,7 +208,7 @@
77
     myBtnAdjust = new StGLCheckboxTextured(myPanelUpper, myPlugin->params.ToShowAdjustImage,
78
                                            iconTexture(stCString("actionColorAdjustOff"), anIconSize),
79
                                            iconTexture(stCString("actionColorAdjust"),    anIconSize),
80
-                                           aLeft + (aBtnIter++) * anIconStep, aTop,
81
+                                           (aBtnIter++) * anIconStep, 0,
82
                                            StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
83
     myBtnAdjust->setDrawShadow(true);
84
     myBtnAdjust->changeMargins() = aButtonMargins;
85
@@ -392,10 +394,18 @@
86
 void StImageViewerGUI::fillPanoramaMenu(StGLMenu* theMenu) {
87
     theMenu->addItem(tr(MENU_VIEW_SURFACE_PLANE),
88
                      myImage->params.ViewMode, StViewSurface_Plain);
89
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_THEATER),
90
+                     myImage->params.ViewMode, StViewSurface_Theater);
91
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_CYLINDER),
92
+                     myImage->params.ViewMode, StViewSurface_Cylinder);
93
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_HEMISPHERE),
94
+                     myImage->params.ViewMode, StViewSurface_Hemisphere);
95
     theMenu->addItem(tr(MENU_VIEW_SURFACE_SPHERE),
96
                      myImage->params.ViewMode, StViewSurface_Sphere);
97
     theMenu->addItem(tr(MENU_VIEW_SURFACE_CUBEMAP),
98
                      myImage->params.ViewMode, StViewSurface_Cubemap);
99
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_CUBEMAP_EAC),
100
+                     myImage->params.ViewMode, StViewSurface_CubemapEAC);
101
     if(myWindow->hasOrientationSensor()) {
102
         theMenu->addItem(tr(myWindow->isPoorOrientationSensor() ? MENU_VIEW_TRACK_HEAD_POOR : MENU_VIEW_TRACK_HEAD),
103
                          myPlugin->params.ToTrackHead);
104
@@ -418,6 +428,8 @@
105
                    myImage->params.TextureFilter, StGLImageProgram::FILTER_NEAREST);
106
     aMenu->addItem(tr(MENU_VIEW_TEXFILTER_LINEAR),
107
                    myImage->params.TextureFilter, StGLImageProgram::FILTER_LINEAR);
108
+    aMenu->addItem(tr(MENU_VIEW_TEXFILTER_TRILINEAR),
109
+                   myImage->params.TextureFilter, StGLImageProgram::FILTER_TRILINEAR);
110
     return aMenu;
111
 }
112
 
113
@@ -546,7 +558,7 @@
114
     const StGLVec3 THE_WHITE(1.0f, 1.0f, 1.0f);
115
     const StString anAbout = tr(ABOUT_DPLUGIN_NAME) + '\n'
116
                            + tr(ABOUT_VERSION) + " " + StVersionInfo::getSDKVersionString()
117
-                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2007-2017", "kirill@sview.ru", "www.sview.ru");
118
+                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2007-2020", "kirill@sview.ru", "www.sview.ru");
119
 
120
     StArgumentsMap anInfo;
121
     anInfo.add(StDictEntry("CPU cores", StString(StThread::countLogicalProcessors()) + StString(" logical processor(s)")));
122
@@ -785,9 +797,14 @@
123
     aParams.add(myPlugin->params.ToStickPanorama);
124
     aParams.add(myPlugin->params.ToFlipCubeZ6x1);
125
     aParams.add(myPlugin->params.ToFlipCubeZ3x2);
126
+    aParams.add(myPlugin->params.ToSwapJPS);
127
     aParams.add(myPlugin->params.ToShowFps);
128
+    aParams.add(myPlugin->params.SlideShowDelay);
129
     aParams.add(myLangMap->params.language);
130
     aParams.add(myPlugin->params.IsMobileUI);
131
+#if defined(_WIN32) || defined(__APPLE__) // implemented only on Windows and macOS
132
+    aParams.add(myPlugin->params.IsExclusiveFullScreen);
133
+#endif
134
     if(isMobile()) {
135
         //aParams.add(myPlugin->params.ToHideStatusBar);
136
         aParams.add(myPlugin->params.ToHideNavBar);
137
@@ -795,10 +812,16 @@
138
         aParams.add(myPlugin->params.ToOpenLast);
139
     }
140
     aParams.add(myPlugin->params.ExitOnEscape);
141
-#if !defined(ST_NO_UPDATES_CHECK)
142
+#if defined(ST_UPDATES_CHECK)
143
     aParams.add(myPlugin->params.CheckUpdatesDays);
144
 #endif
145
 
146
+    if(!myWindow->isMobile()) {
147
+        StHandle<StBoolParamNamed> aDefDrawerParam = myPlugin->createDefaultDrawerParam(stCString("StImageViewer"),
148
+                                                                                        stCString("sView launcher starts Image Viewer"));
149
+        aParams.add(aDefDrawerParam);
150
+    }
151
+
152
     StInfoDialog* aDialog = new StInfoDialog(myPlugin, this, tr(MENU_HELP_SETTINGS), scale(768), scale(300));
153
 
154
     const int aWidthMax  = aDialog->getContent()->getRectPx().width();
155
@@ -1148,18 +1171,22 @@
156
 
157
 void StImageViewerGUI::doOpenFile(const size_t ) {
158
     StGLOpenFile* aDialog = new StGLOpenFile(this, tr(DIALOG_OPEN_FILE), tr(BUTTON_CLOSE));
159
-    aDialog->setMimeList(myPlugin->myLoader->getMimeList());
160
-#if defined(_WIN32)
161
-    //
162
-#else
163
-    aDialog->addHotItem("/", "Root");
164
-#endif
165
-    aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_SdCard));
166
+
167
+    const StString anSdCardPath = getResourceManager()->getFolder(StResourceManager::FolderId_SdCard);
168
+    if(!anSdCardPath.isEmpty()) {
169
+        StString aFolder, aName;
170
+        StFileNode::getFolderAndFile(anSdCardPath, aFolder, aName);
171
+        aDialog->addHotItem(anSdCardPath, stUtfTools::isInteger(aName) ? (StString("sdcard") + aName) : aName);
172
+    }
173
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Downloads));
174
+    aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Documents));
175
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Pictures));
176
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Photos));
177
     aDialog->signals.onFileSelected = stSlot(myPlugin, &StImageViewer::doOpen1FileFromGui);
178
 
179
+    aDialog->setMimeList(myPlugin->myLoader->getMimeListImages(), "Images", false);
180
+    aDialog->setMimeList(myPlugin->myLoader->getMimeListVideo(),  "Videos", true);
181
+
182
     if(myPlugin->params.lastFolder.isEmpty()) {
183
         StHandle<StFileNode> aCurrFile = myPlugin->myPlayList->getCurrentFile();
184
         if(!aCurrFile.isNull()) {
185
@@ -1258,6 +1285,12 @@
186
     }
187
 
188
     myImage = new StGLImageRegion(this, aTextureQueue, true);
189
+    myImage->changeIconPrev()->setTexturePath(iconTexture(stCString("actionBack"), scaleIcon(64)));
190
+    myImage->changeIconPrev()->setDrawShadow(true);
191
+    myImage->changeIconNext()->setTexturePath(iconTexture(stCString("actionNext"), scaleIcon(64)));
192
+    myImage->changeIconNext()->setDrawShadow(true);
193
+    myImage->signals.onOpenItem = stSlot(myPlugin, &StImageViewer::doFileNext);
194
+    myImage->setPlayList(thePlayList);
195
     myImage->params.DisplayMode->setName(tr(MENU_VIEW_DISPLAY_MODE));
196
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_STEREO]     = tr(MENU_VIEW_DISPLAY_MODE_STEREO);
197
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_ONLY_LEFT]  = tr(MENU_VIEW_DISPLAY_MODE_LEFT);
198
@@ -1311,8 +1344,32 @@
199
     }
200
 }
201
 
202
+void StImageViewerGUI::doGesture(const StGestureEvent& theEvent) {
203
+    if(myImage == NULL) {
204
+        return;
205
+    }
206
+
207
+    if(theEvent.Type == stEvent_Gesture1Tap) {
208
+        myTapTimer.restart();
209
+    } else if(theEvent.Type == stEvent_Gesture1DoubleTap) {
210
+        myTapTimer.stop();
211
+    }
212
+
213
+    for(StGLWidget *aChildIter(getChildren()->getLast()), *aChildActive(NULL); aChildIter != NULL;) {
214
+        aChildActive = aChildIter;
215
+        aChildIter   = aChildIter->getPrev();
216
+        if(aChildActive->isVisibleAndPointIn(getCursorZo())) {
217
+            if(aChildActive == myImage) {
218
+                myImage->doGesture(theEvent);
219
+            }
220
+            return;
221
+        }
222
+    }
223
+}
224
+
225
 void StImageViewerGUI::setVisibility(const StPointD_t& theCursor,
226
-                                     bool              toForceHide) {
227
+                                     bool theToForceHide,
228
+                                     bool theToForceShow) {
229
     const bool toShowAdjust   = myPlugin->params.ToShowAdjustImage->getValue();
230
     const bool toShowPlayList = myPlugin->params.ToShowPlayList->getValue();
231
     const bool hasMainMenu    =  myPlugin->params.ToShowMenu->getValue()
232
@@ -1321,10 +1378,29 @@
233
                              &&  myPlugin->params.ToShowTopbar->getValue()
234
                              &&  myPanelUpper  != NULL;
235
     const bool hasBottomPanel = !myIsMinimalGUI
236
+                             &&  myPlugin->params.ToShowBottom->getValue()
237
                              &&  myPanelBottom != NULL;
238
-    const bool isMouseActive  = myWindow->isMouseMoved();
239
 
240
     StHandle<StStereoParams> aParams = myImage->getSource();
241
+    if(aParams.isNull() && !myEmptyTimer.isOn()
242
+    && !myPlugin->myPlayList->isEmpty()) {
243
+        myEmptyTimer.restart();
244
+    } else {
245
+        myEmptyTimer.stop();
246
+    }
247
+    if(myEmptyTimer.getElapsedTime() >= 2.5) {
248
+        myVisibilityTimer.restart();
249
+        myEmptyTimer.stop();
250
+    }
251
+    if(myTapTimer.getElapsedTime() >= 0.5) {
252
+        myVisibilityTimer.restart();
253
+        myTapTimer.stop();
254
+    }
255
+    if(theToForceShow) {
256
+        myVisibilityTimer.restart();
257
+    }
258
+    const bool isMouseActive  = myWindow->isMouseMoved();
259
+
260
     StFormat aSrcFormat = (StFormat )myPlugin->params.SrcStereoFormat->getValue();
261
     if(aSrcFormat == StFormat_AUTO
262
     && !aParams.isNull()) {
263
@@ -1337,8 +1413,7 @@
264
 
265
     const double aStillTime = myVisibilityTimer.getElapsedTime();
266
     myIsVisibleGUI = isMouseActive
267
-        || aParams.isNull()
268
-        || aStillTime < 2.0
269
+        || aStillTime < THE_VISIBILITY_IDLE_TIME
270
         || (hasUpperPanel  && myPanelUpper ->isPointIn(theCursor))
271
         || (hasBottomPanel && myPanelBottom->isPointIn(theCursor))
272
         || (myPlayList != NULL && toShowPlayList && myPlayList->isPointIn(theCursor))
273
@@ -1347,8 +1422,8 @@
274
     if(isMouseActive) {
275
         myVisibilityTimer.restart();
276
     }
277
-    const bool  toShowAll = !myIsMinimalGUI && myIsVisibleGUI && !toForceHide;
278
-    const float anOpacity = (float )myVisLerp.perform(toShowAll, toForceHide);
279
+    const bool  toShowAll = !myIsMinimalGUI && myIsVisibleGUI && !theToForceHide;
280
+    const float anOpacity = (float )myVisLerp.perform(toShowAll, theToForceHide || theToForceShow);
281
 
282
     if(myMenuRoot != NULL) {
283
         myMenuRoot->setOpacity(hasMainMenu ? anOpacity : 0.0f, true);
284
@@ -1374,7 +1449,7 @@
285
     }
286
     if(myPlayList != NULL
287
     && toShowPlayList) {
288
-        myPlayList->setOpacity(anOpacity, true);
289
+        myPlayList->setOpacity(myPlugin->params.ToShowBottom->getValue() ? anOpacity : 0.0f, true);
290
     }
291
     if(myBtnFull != NULL) {
292
         if(myIsMinimalGUI
293
@@ -1413,9 +1488,9 @@
294
     bool toShowPano = aViewMode != StViewSurface_Plain;
295
     if(!toShowPano
296
     && !aParams.isNull()
297
-    &&  st::probePanorama(aParams->StereoFormat,
298
+    /*&&  st::probePanorama(aParams->StereoFormat,
299
                           aParams->Src1SizeX, aParams->Src1SizeY,
300
-                          aParams->Src2SizeX, aParams->Src2SizeY) != StPanorama_OFF) {
301
+                          aParams->Src2SizeX, aParams->Src2SizeY) != StPanorama_OFF*/) {
302
         toShowPano = true;
303
     }
304
     if(myBtnPanorama != NULL) {
305
@@ -1451,9 +1526,13 @@
306
         } else if(::isPointIn(myBtnPanorama, theCursor)) {
307
             size_t aTrPano = MENU_VIEW_SURFACE_PLANE;
308
             switch(aViewMode) {
309
-                case StViewSurface_Plain:   aTrPano = MENU_VIEW_SURFACE_PLANE;   break;
310
-                case StViewSurface_Sphere:  aTrPano = MENU_VIEW_SURFACE_SPHERE;  break;
311
-                case StViewSurface_Cubemap: aTrPano = MENU_VIEW_SURFACE_CUBEMAP; break;
312
+                case StViewSurface_Plain:      aTrPano = MENU_VIEW_SURFACE_PLANE;   break;
313
+                case StViewSurface_Theater:    aTrPano = MENU_VIEW_SURFACE_THEATER; break;
314
+                case StViewSurface_Sphere:     aTrPano = MENU_VIEW_SURFACE_SPHERE;  break;
315
+                case StViewSurface_Hemisphere: aTrPano = MENU_VIEW_SURFACE_HEMISPHERE; break;
316
+                case StViewSurface_Cubemap:    aTrPano = MENU_VIEW_SURFACE_CUBEMAP;  break;
317
+                case StViewSurface_CubemapEAC: aTrPano = MENU_VIEW_SURFACE_CUBEMAP_EAC; break;
318
+                case StViewSurface_Cylinder:   aTrPano = MENU_VIEW_SURFACE_CYLINDER; break;
319
             }
320
             myDescr->setText(tr(MENU_VIEW_PANORAMA) + "\n" + tr(aTrPano));
321
         } else {
322
@@ -1486,7 +1565,20 @@
323
                                   float theAspect) {
324
     const int aNewSizeX  = theViewPort.width();
325
     const int aNewSizeY  = theViewPort.height();
326
-    const int aWorkRight = stMax(aNewSizeX - theMargins.right - theMargins.left, 2);
327
+    int aGapTopX = 0, aGapTopY = 0, aGapBotX = 0, aGapBotY = 0;
328
+    if(isMobile()) {
329
+        // add gap for hidden system navigation buttons
330
+        static const int THE_NAVIGATION_GAPX = 32;
331
+        static const int THE_NAVIGATION_GAPY = 16;
332
+        if(theAspect < 9.0 / 16.0 && theAspect > 0.0) {
333
+            aGapTopY = aGapBotY = stMax(0, scale(stMin(THE_NAVIGATION_GAPY, int((1.0 / theAspect * 360) - 360 * 2))));
334
+        } else if(theAspect > 9.0 / 16.0) {
335
+            aGapTopX = aGapBotX = stMax(0, scale(stMin(THE_NAVIGATION_GAPX, int((theAspect * 360) - 360 * 2))));
336
+        }
337
+    } else {
338
+        aGapTopY = scale(DISPL_Y_REGION_UPPER);
339
+        aGapTopX = scale(DISPL_X_REGION_UPPER);
340
+    }
341
 
342
     // image should fit entire view
343
     myImage->changeRectPx().top()    = -theMargins.top;
344
@@ -1495,12 +1587,16 @@
345
     myImage->changeRectPx().right()  = -theMargins.left + aNewSizeX;
346
 
347
     if(myPanelUpper != NULL) {
348
-        myPanelUpper->changeRectPx().right() = aWorkRight;
349
+        myPanelUpper->changeRectPx().top()   = aGapTopY;
350
+        myPanelUpper->changeRectPx().left()  = aGapTopX;
351
+        myPanelUpper->changeRectPx().right() = aGapTopX + stMax(aNewSizeX - theMargins.right - theMargins.left - 2 * aGapTopX, 2);
352
         myIsMinimalGUI = (myWindow->isMovable() || myWindow->hasFullscreenMode()) && !isMobile()
353
                      && (aNewSizeY < scale(400) || aNewSizeX < scale(400));
354
     }
355
     if(myPanelBottom != NULL) {
356
-        myPanelBottom->changeRectPx().right() = aWorkRight;
357
+        myPanelBottom->changeRectPx().top()   = -aGapBotY;
358
+        myPanelBottom->changeRectPx().left()  = aGapBotX;
359
+        myPanelBottom->changeRectPx().right() = aGapBotX + stMax(aNewSizeX - theMargins.right - theMargins.left - 2 * aGapBotX, 2);
360
     }
361
     StGLRootWidget::stglResize(theViewPort, theMargins, theAspect);
362
 }
363
sview-17_04.tar.gz/StImageViewer/StImageViewerGUI.h -> sview-20_08.tar.gz/StImageViewer/StImageViewerGUI.h Changed
33
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -102,8 +102,14 @@
9
                                      float theAspect) ST_ATTR_OVERRIDE;
10
     ST_LOCAL virtual void stglDraw(unsigned int theView) ST_ATTR_OVERRIDE;
11
 
12
+    /**
13
+     * Handle gesture.
14
+     */
15
+    ST_LOCAL void doGesture(const StGestureEvent& theEvent);
16
+    ST_LOCAL bool isVisibleGUI() const { return myVisLerp.getValue() > 0.0; }
17
     ST_LOCAL void setVisibility(const StPointD_t& theCursor,
18
-                                bool              toForceHide);
19
+                                bool theToForceHide,
20
+                                bool theToForceShow = false);
21
 
22
         public:
23
 
24
@@ -203,6 +209,8 @@
25
     StWindow*           myWindow;           //!< link to the window instance
26
     StTranslations*     myLangMap;          //!< translated strings map
27
     StTimer             myVisibilityTimer;  //!< minimum visible delay
28
+    StTimer             myEmptyTimer;       //!< empty list delay
29
+    StTimer             myTapTimer;         //!< single tap delay
30
     StGLAnimationLerp   myVisLerp;
31
 
32
     StGLImageRegion*    myImage;            //!< the main image
33
sview-17_04.tar.gz/StImageViewer/StImageViewerStrings.cpp -> sview-20_08.tar.gz/StImageViewer/StImageViewerStrings.cpp Changed
77
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2013-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -119,10 +119,16 @@
9
                "Plane");
10
     theStrings(MENU_VIEW_SURFACE_SPHERE,
11
                "Sphere");
12
+    theStrings(MENU_VIEW_SURFACE_HEMISPHERE,
13
+               "Hemisphere");
14
     theStrings(MENU_VIEW_SURFACE_CYLINDER,
15
                "Cylinder");
16
     theStrings(MENU_VIEW_SURFACE_CUBEMAP,
17
                "Cubemap");
18
+    theStrings(MENU_VIEW_SURFACE_THEATER,
19
+               "Theater");
20
+    theStrings(MENU_VIEW_SURFACE_CUBEMAP_EAC,
21
+               "Equiangular cubemap");
22
     theStrings(MENU_VIEW_TRACK_HEAD,
23
                "Track orientation");
24
     theStrings(MENU_VIEW_TRACK_HEAD_POOR,
25
@@ -153,6 +159,8 @@
26
                "Nearest");
27
     theStrings(MENU_VIEW_TEXFILTER_LINEAR,
28
                "Linear"),
29
+    theStrings(MENU_VIEW_TEXFILTER_TRILINEAR,
30
+               "Trilinear"),
31
     theStrings(MENU_CHANGE_DEVICE,
32
                "Change Device");
33
     theStrings(MENU_ABOUT_RENDERER,
34
@@ -161,6 +169,8 @@
35
                "Show FPS");
36
     theStrings(MENU_VSYNC,
37
                "VSync");
38
+    theStrings(MENU_EXCLUSIVE_FULLSCREEN,
39
+               "Exclusive Fullscreen mode");
40
     theStrings(ABOUT_DPLUGIN_NAME,
41
                "sView - Image Viewer");
42
     theStrings(ABOUT_VERSION,
43
@@ -237,6 +247,8 @@
44
                "Hide system navigation bar");
45
     theStrings(OPTION_OPEN_LAST_ON_STARTUP,
46
                "Open last viewed file on startup");
47
+    theStrings(OPTION_SWAP_JPS,
48
+               "Swap JPS/PNS views order");
49
 
50
     theStrings(UPDATES_NOTIFY,
51
                "A new version of sView is available on the official site www.sview.ru.\n"
52
@@ -286,6 +298,8 @@
53
                "msec");
54
     theStrings(INFO_PIXEL_RATIO,
55
                "Pixel ratio");
56
+    theStrings(INFO_PIXEL_FORMAT,
57
+               "Pixel format");
58
     theStrings(INFO_COLOR_MODEL,
59
                "Color model");
60
     theStrings(INFO_NO_SRCFORMAT,
61
@@ -451,6 +465,15 @@
62
     addAction(theStrings, StImageViewer::Action_PanoramaOnOff,
63
               "DoPanoramaOnOff",
64
               "Enable/disable panorama mode");
65
+    addAction(theStrings, StImageViewer::Action_ShowGUI,
66
+              "DoShowGUI",
67
+              "Show/hide GUI");
68
+
69
+    theStrings.addAlias("DoOutStereoNormal",       MENU_VIEW_DISPLAY_MODE_STEREO);
70
+    theStrings.addAlias("DoOutStereoLeftView",     MENU_VIEW_DISPLAY_MODE_LEFT);
71
+    theStrings.addAlias("DoOutStereoRightView",    MENU_VIEW_DISPLAY_MODE_RIGHT);
72
+    theStrings.addAlias("DoOutStereoParallelPair", MENU_VIEW_DISPLAY_MODE_PARALLEL);
73
+    theStrings.addAlias("DoOutStereoCrossEyed",    MENU_VIEW_DISPLAY_MODE_CROSSYED);
74
 }
75
 
76
 };
77
sview-17_04.tar.gz/StImageViewer/StImageViewerStrings.h -> sview-20_08.tar.gz/StImageViewer/StImageViewerStrings.h Changed
59
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StImageViewer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -84,6 +84,7 @@
9
 
10
         MENU_VIEW_TEXFILTER_NEAREST = 1260,
11
         MENU_VIEW_TEXFILTER_LINEAR  = 1261,
12
+        MENU_VIEW_TEXFILTER_TRILINEAR = 1263,
13
 
14
         MENU_VIEW_ADJUST_RESET      = 1270,
15
         MENU_VIEW_ADJUST_BRIGHTNESS = 1271,
16
@@ -94,17 +95,21 @@
17
         MENU_VIEW_SURFACE_SPHERE    = 1281,
18
         MENU_VIEW_SURFACE_CYLINDER  = 1282,
19
         MENU_VIEW_SURFACE_CUBEMAP   = 1283,
20
+        MENU_VIEW_SURFACE_HEMISPHERE= 1284,
21
         MENU_VIEW_TRACK_HEAD        = 1285,
22
         MENU_VIEW_TRACK_HEAD_POOR   = 1286,
23
         MENU_VIEW_STICK_PANORAMA360 = 1288,
24
         MENU_VIEW_FLIPZ_CUBE6x1     = 1291,
25
         MENU_VIEW_FLIPZ_CUBE3x2     = 1292,
26
+        MENU_VIEW_SURFACE_CUBEMAP_EAC = 1293,
27
+        MENU_VIEW_SURFACE_THEATER   = 1294,
28
 
29
         // Root -> Output -> Change Device menu
30
         MENU_CHANGE_DEVICE  = 1400,
31
         MENU_ABOUT_RENDERER = 1401,
32
         MENU_SHOW_FPS       = 1402,
33
         MENU_VSYNC          = 1403,
34
+        MENU_EXCLUSIVE_FULLSCREEN = 1404,
35
 
36
         // Root -> Help menu
37
         MENU_HELP         = 1500,
38
@@ -138,6 +143,7 @@
39
         OPTION_EXIT_ON_ESCAPE_WINDOWED     = 1705,
40
         OPTION_HIDE_NAVIGATION_BAR         = 1710,
41
         OPTION_OPEN_LAST_ON_STARTUP        = 1711,
42
+        OPTION_SWAP_JPS                    = 1712,
43
 
44
         // Open/Save dialogs
45
         DIALOG_OPEN_FILE       = 2000,
46
@@ -181,10 +187,11 @@
47
         INFO_LOAD_TIME         = 5004,
48
         INFO_TIME_MSEC         = 5005,
49
         INFO_PIXEL_RATIO       = 5006,
50
-        INFO_COLOR_MODEL       = 5007,
51
+        INFO_PIXEL_FORMAT      = 5007,
52
         INFO_NO_SRCFORMAT      = 5008,
53
         INFO_WRONG_SRCFORMAT   = 5009,
54
         INFO_NO_SRCFORMAT_EX   = 5011,
55
+        INFO_COLOR_MODEL       = 5012,
56
 
57
         // metadata keys
58
         METADATA_JPEG_COMMENT     = 5100,
59
sview-17_04.tar.gz/StImageViewer/lang/chinese/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/chinese/StImageViewer.lng Changed
50
 
1
@@ -47,6 +47,7 @@
2
 ?1252=Heal anamorphic 1080p/720p
3
 1260=接近
4
 1261=线状
5
+?1263=Trilinear
6
 1270=重置默认
7
 1271=亮度
8
 1272=饱和度
9
@@ -55,15 +56,19 @@
10
 1281=球面
11
 1282=圆柱
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1288=Stick at panorama 360°
17
 ?1291=Cubemap 6x1 - flip Z
18
 ?1292=Cubemap 3x2 - flip Z
19
+?1293=Equiangular cubemap
20
+?1294=Theater
21
 1400=改变设备
22
 1401=关于插件...
23
 1402=显示 FPS
24
 1403=同步
25
+?1404=Exclusive Fullscreen mode
26
 1500=帮助
27
 1501=关于...
28
 1502=更新检查
29
@@ -90,6 +95,7 @@
30
 ?1705=On one click windowed mode
31
 ?1710=Hide system navigation bar
32
 ?1711=Open last viewed file on startup
33
+?1712=Swap JPS/PNS views order
34
 2000=选择图片文件打开
35
 2001=选择左画面图片打开
36
 2002=选择右画面图片文件打开
37
@@ -128,6 +134,7 @@
38
 5008=(不存储在元数据)
39
 5009=(不匹配的元数据)
40
 5011=(不存储在元数据中,\n但检测到文件名称)
41
+?5012=Color model
42
 5100=JPEG 说明
43
 5101=JPS 说明
44
 5200=相机生产商
45
@@ -177,3 +184,4 @@
46
 ?6040=X Rotation - up
47
 ?6041=X Rotation - down
48
 ?6042=Enable/disable panorama mode
49
+?6043=Show/hide GUI
50
sview-17_04.tar.gz/StImageViewer/lang/czech/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/czech/StImageViewer.lng Changed
55
 
1
@@ -48,6 +48,7 @@
2
 ?1252=Heal anamorphic 1080p/720p
3
 1260=Sousední
4
 1261=Lineární
5
+?1263=Trilinear
6
 1270=Resetovat nastavení
7
 1271=Jas
8
 1272=Sytost
9
@@ -56,15 +57,19 @@
10
 1281=Koule
11
 1282=Válec
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1288=Stick at panorama 360°
17
 ?1291=Cubemap 6x1 - flip Z
18
 ?1292=Cubemap 3x2 - flip Z
19
+?1293=Equiangular cubemap
20
+?1294=Theater
21
 1400=Zobrazovací zařizení
22
 1401=O modulu
23
 1402=Zobrazovat snímkování (fps)
24
 1403=Vertikální synchronizace
25
+?1404=Exclusive Fullscreen mode
26
 1500=Nápověda
27
 1501=O aplikaci sView…
28
 1502=Aktualizace
29
@@ -91,6 +96,7 @@
30
 ?1705=On one click windowed mode
31
 ?1710=Hide system navigation bar
32
 ?1711=Open last viewed file on startup
33
+?1712=Swap JPS/PNS views order
34
 2000=Otevřít
35
 2001=Otevřít LEVÝ
36
 2002=Otevřít PRAVÝ
37
@@ -125,10 +131,11 @@
38
 5004=Načítání
39
 5005=ms
40
 5006=Poměr stran pixelu
41
-5007=Barevný model
42
+5007=Formát pixelu
43
 5008=(metada nejsou v informaci obsažena)
44
 5009=(neobsahuje metadata)
45
 5011=(informace není obsažena v metadatech,\nale byla přidělena podle jména souboru)
46
+5012=Barevný model
47
 5100=JPEG komentář
48
 5101=JPS komentář
49
 5200=Výrobce kamery
50
@@ -178,3 +185,4 @@
51
 ?6040=X Rotation - up
52
 ?6041=X Rotation - down
53
 ?6042=Enable/disable panorama mode
54
+?6043=Show/hide GUI
55
sview-17_04.tar.gz/StImageViewer/lang/english/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/english/StImageViewer.lng Changed
55
 
1
@@ -47,6 +47,7 @@
2
 1252=Heal anamorphic 1080p/720p
3
 1260=Nearest
4
 1261=Linear
5
+1263=Trilinear
6
 1270=Reset to defaults
7
 1271=Brightness
8
 1272=Saturation
9
@@ -55,15 +56,19 @@
10
 1281=Sphere
11
 1282=Cylinder
12
 1283=Cubemap
13
+1284=Hemisphere
14
 1285=Track orientation
15
 1286=Track orientation (poor)
16
 1288=Stick at panorama 360°
17
 1291=Cubemap 6x1 - flip Z
18
 1292=Cubemap 3x2 - flip Z
19
+1293=Equiangular cubemap
20
+1294=Theater
21
 1400=Change device
22
 1401=About Plugin...
23
 1402=Show FPS
24
 1403=VSync
25
+1404=Exclusive Fullscreen mode
26
 1500=Help
27
 1501=About...
28
 1502=Check for updates
29
@@ -90,6 +95,7 @@
30
 1705=On one click windowed mode
31
 1710=Hide system navigation bar
32
 1711=Open last viewed file on startup
33
+1712=Swap JPS/PNS views order
34
 2000=Choose the image file to open
35
 2001=Choose LEFT image file to open
36
 2002=Choose RIGHT image file to open
37
@@ -124,10 +130,11 @@
38
 5004=Load time
39
 5005=ms
40
 5006=Pixel ratio
41
-5007=Color model
42
+5007=Pixel format
43
 5008=(does not stored in metadata)
44
 5009=(does not match metadata)
45
 5011=(does not stored in metadata,\nbut detected from file name)
46
+5012=Color model
47
 5100=JPEG Comment
48
 5101=JPS Comment
49
 5200=Camera Maker
50
@@ -177,3 +184,4 @@
51
 6040=X Rotation - up
52
 6041=X Rotation - down
53
 6042=Enable/disable panorama mode
54
+6043=Show/hide GUI
55
sview-17_04.tar.gz/StImageViewer/lang/french/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/french/StImageViewer.lng Changed
55
 
1
@@ -47,6 +47,7 @@
2
 ?1252=Heal anamorphic 1080p/720p
3
 1260=Plus proche
4
 1261=Lineaire
5
+1263=Trilinéaire
6
 1270=Rétablir par défaut
7
 1271=Brightness
8
 1272=Saturation
9
@@ -55,15 +56,19 @@
10
 1281=Sphère
11
 1282=Cylindre
12
 1283=Cubemap
13
+1284=Hémisphère
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1288=Stick at panorama 360°
17
 ?1291=Cubemap 6x1 - flip Z
18
 ?1292=Cubemap 3x2 - flip Z
19
+?1293=Equiangular cubemap
20
+1294=Théâtre
21
 1400=Changer la sortie
22
 1401=A propos du Plugin...
23
 1402=Voir I/S
24
 1403=Synchro Vert.
25
+?1404=Exclusive Fullscreen mode
26
 1500=Aide
27
 1501=A Propos...
28
 1502=Vérifier nouvelle version
29
@@ -90,6 +95,7 @@
30
 ?1705=On one click windowed mode
31
 ?1710=Hide system navigation bar
32
 ?1711=Open last viewed file on startup
33
+1712=JPS/PNS échange de vues pour
34
 2000=Choix du fichier image à ouvrir
35
 2001=Choix du fichier image Gauche à ouvrir
36
 2002=Choix du fichier image Droite à ouvrir
37
@@ -124,10 +130,11 @@
38
 5004=Temps de démarrage
39
 5005=ms
40
 5006=Pixel ratio
41
-5007=Modèle colorimétrique
42
+5007=Pixel format
43
 ?5008=(does not stored in metadata)
44
 ?5009=(does not match metadata)
45
 ?5011=(does not stored in metadata,\nbut detected from file name)
46
+5012=Modèle colorimétrique
47
 5100=JPEG commentaire
48
 5101=JPS commentaire
49
 5200=Camera Maker
50
@@ -177,3 +184,4 @@
51
 ?6040=X Rotation - up
52
 ?6041=X Rotation - down
53
 6042=Activer / désactiver le mode panorama
54
+6043=Masquer l'interface
55
sview-17_04.tar.gz/StImageViewer/lang/german/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/german/StImageViewer.lng Changed
55
 
1
@@ -47,6 +47,7 @@
2
 ?1252=Heal anamorphic 1080p/720p
3
 1260=Nearest
4
 1261=Linear
5
+1263=Trilinear
6
 1270=Auf Standardwerte zurücksetzen
7
 1271=Helligkeit
8
 1272=Sättigung
9
@@ -55,15 +56,19 @@
10
 1281=Kugel
11
 1282=Zylinder
12
 1283=Cubemap
13
+1284=Hemisphäre
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1288=Stick at panorama 360°
17
 ?1291=Cubemap 6x1 - flip Z
18
 ?1292=Cubemap 3x2 - flip Z
19
+?1293=Equiangular cubemap
20
+1294=Theater
21
 1400=Gerät ändern
22
 1401=Über Plugin...
23
 1402=FPS anzeigen
24
 1403=VSync
25
+1404=Exklusiver Vollbildmodus
26
 1500=Hilfe
27
 1501=Über...
28
 1502=Nach Updates suchen
29
@@ -90,6 +95,7 @@
30
 ?1705=Only when windowed
31
 1710=Navigationsleiste ausblenden
32
 ?1711=Open last viewed file on startup
33
+1712=JPS/PNS-Ansichten, um zu tauschen
34
 2000=Wählen die Bilddatei zu öffnen
35
 2001=Wählen die linke Bilddatei zu öffnen
36
 2002=Wählen die rechte Bilddatei zu öffnen
37
@@ -124,10 +130,11 @@
38
 5004=Ladezeit
39
 5005=ms
40
 5006=Pixelseitenverhältnis
41
-5007=Farbmodell
42
+5007=Pixel format
43
 5008=(nicht in Metadaten gespeichert)
44
 5009=(keine Metadaten übereinstimmen)
45
 5011=(nicht in Metadaten gespeichert,\nsondern von Dateinamen detektiert)
46
+5012=Farbmodell
47
 5100=JPEG Kommentar
48
 5101=JPS Kommentar
49
 5200=Kamerahersteller
50
@@ -177,3 +184,4 @@
51
 6040=X-Drehung - nach oben
52
 6041=X-Drehung - nach unten
53
 6042=Aktivieren / Deaktivieren der Panorama-Modus
54
+6043=GUI ausblenden
55
sview-17_04.tar.gz/StImageViewer/lang/korean/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/korean/StImageViewer.lng Changed
55
 
1
@@ -48,6 +48,7 @@
2
 ?1252=Heal anamorphic 1080p/720p
3
 ?1260=Nearest
4
 ?1261=Linear
5
+?1263=Trilinear
6
 1270=기본값으로 리셋
7
 1271=밝기
8
 ?1272=Saturation
9
@@ -56,15 +57,19 @@
10
 ?1281=Sphere
11
 ?1282=Cylinder
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1288=Stick at panorama 360°
17
 ?1291=Cubemap 6x1 - flip Z
18
 ?1292=Cubemap 3x2 - flip Z
19
+?1293=Equiangular cubemap
20
+?1294=Theater
21
 1400=장치 변경
22
 ?1401=About Plugin...
23
 ?1402=Show FPS
24
 ?1403=VSync
25
+?1404=Exclusive Fullscreen mode
26
 1500=도움말
27
 1501=이 프로그램에 대해...
28
 1502=업데이트 확인
29
@@ -91,6 +96,7 @@
30
 ?1705=On one click windowed mode
31
 ?1710=Hide system navigation bar
32
 ?1711=Open last viewed file on startup
33
+?1712=Swap JPS/PNS views order
34
 2000=열어볼 이미지 파일 선택
35
 2001=왼쪽 이미지 선택
36
 2002=오른쪽 이미지 선택
37
@@ -125,10 +131,11 @@
38
 ?5004=Load time
39
 ?5005=ms
40
 ?5006=Pixel ratio
41
-?5007=Color model
42
+?5007=Pixel format
43
 ?5008=(does not stored in metadata)
44
 ?5009=(does not match metadata)
45
 ?5011=(does not stored in metadata,\nbut detected from file name)
46
+?5012=Color model
47
 ?5100=JPEG Comment
48
 ?5101=JPS Comment
49
 ?5200=Camera Maker
50
@@ -178,3 +185,4 @@
51
 ?6040=X Rotation - up
52
 ?6041=X Rotation - down
53
 ?6042=Enable/disable panorama mode
54
+?6043=Show/hide GUI
55
sview-17_04.tar.gz/StImageViewer/lang/russian/StImageViewer.lng -> sview-20_08.tar.gz/StImageViewer/lang/russian/StImageViewer.lng Changed
59
 
1
@@ -45,8 +45,9 @@
2
 1250=Исходное
3
 1251=Запомнить
4
 ?1252=Heal anamorphic 1080p/720p
5
-1260=Nearest
6
-1261=Linear
7
+1260=Без сглаживания
8
+1261=Линейное
9
+1263=Трилинейное
10
 1270=Сбросить настройки
11
 1271=Яркость
12
 1272=Насыщенность
13
@@ -55,15 +56,19 @@
14
 1281=Сфера
15
 1282=Цилиндр
16
 1283=Куб
17
+1284=Полусфера
18
 1285=Отслеживать ориентацию
19
 1286=Отслеживать ориентацию (poor)
20
 1288=Закрепить панорамный режим 360°
21
 1291=Кубмапа 6x1 - инвертировать Z
22
 1292=Кубмапа 3x2 - инвертировать Z
23
+?1293=Equiangular cubemap
24
+1294=Киноэкран
25
 1400=Выбрать устройство
26
 1401=О модуле...
27
 1402=Отображать FPS
28
 1403=Верт. синхронизация
29
+1404=Эксклюзивный полноэкранный режим
30
 1500=Помощь
31
 1501=О программе...
32
 1502=Проверить обновления
33
@@ -90,6 +95,7 @@
34
 1705=Только в оконном режиме
35
 1710=Скрыть панель навигации
36
 1711=Открывать последний файл при старте
37
+1712=Поменять ракурсы местами в JPS/PNS
38
 2000=Выберите картинку
39
 2001=Выберите файл с ЛЕВЫМ ракурсом
40
 2002=Выберите файл с ПРАВЫМ ракурсом
41
@@ -124,10 +130,11 @@
42
 5004=Время загрузки
43
 5005=мс
44
 5006=Пропорции пикселя
45
-5007=Color model
46
+5007=Пиксельный формат
47
 5008=(информация отсутствует в метаданных)
48
 5009=(не соответствует метаданным)
49
 5011=(информация отсутствует в метаданных,\nно была определена по имени файла)
50
+5012=Color model
51
 5100=JPEG комментарий
52
 5101=JPS комментарий
53
 5200=Производитель камеры
54
@@ -177,3 +184,4 @@
55
 6040=X наклон - наверх
56
 6041=X наклон - вниз
57
 6042=Включить/выключить панорамный режим
58
+6043=Скрыть интерфейс
59
sview-20_08.tar.gz/StImageViewer/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StImageViewer/lang/spanish/StImageViewer.lng Added
188
 
1
@@ -0,0 +1,186 @@
2
+# Spanish translation file for StImageViewer
3
+--------
4
+1000=Anterior imagen
5
+1001=Siguiente imagen
6
+1002=Cambiar izquierdo/derecho
7
+1003=Revertir cambio izquierdo/derecho
8
+1004=Formato estereoscópico:
9
+1015=Abrir otra imagen
10
+1028=Mostrar/Ocultar lista de reproducción
11
+1029=Cambiar entre\npantalla completa/ventana
12
+1100=Medios
13
+1101=Abrir imagen...
14
+1102=Guardar imagen como...
15
+1103=Formato estereoscópico
16
+1104=Información de la imagen
17
+1109=Salir
18
+1110=Desde un archivo
19
+1111=Archivos izquierdo+derecho
20
+1130=Fuente
21
+1131=Mono
22
+1132=Vista cruzada
23
+1133=Par paralelo
24
+1134=Sobre/bajo (D/I)
25
+1135=Sobre/bajo (I/D)
26
+1136=Entrelazado
27
+1137=Anaglifo rojo/cian
28
+1138=Anaglifo verde/rojo+azul
29
+1139=Anaglifo amarillo/azul
30
+1142=2 canales
31
+1200=Ver
32
+1201=Salida estéreo
33
+1202=Pantalla completa
34
+1203=Restablecer
35
+1204=Cambiar izquierdo/derecho
36
+1205=Relación de visualización
37
+1206=Filtro más suave
38
+1207=Ajustar imagen
39
+1208=Panorámica
40
+1210=Estéreo
41
+1211=Vista izquierda
42
+1212=Vista derecha
43
+1213=Par paralelo
44
+1214=Vista cruzada
45
+1250=Fuente
46
+1251=Conservar al reiniciar
47
+1252=Corregir anamórfico 1080p/720p
48
+1260=Más cercano
49
+1261=Lineal
50
+1263=Trilineal
51
+1270=Restablecer predeterminados
52
+1271=Brillo
53
+1272=Saturación
54
+1273=Gamma
55
+1280=Desactivado
56
+1281=Esfera
57
+1282=Cilindro
58
+1283=Cubemap
59
+1284=Hemisferio
60
+1285=Orientación de pista
61
+1286=Orientación de pista (deficiente)
62
+1288=Mantener en panorámica de 360°
63
+1291=Cubemap 6x1 - voltear Z
64
+1292=Cubemap 3x2 - voltear Z
65
+?1293=Equiangular cubemap
66
+1294=Teatro
67
+1400=Cambiar dispositivo
68
+1401=Acerca del complemento...
69
+1402=Mostrar FPS
70
+1403=Sincronización vertical
71
+1404=Modo de pantalla completa exclusiva
72
+1500=Ayuda
73
+1501=Acerca de...
74
+1502=Buscar actualizaciones
75
+1503=Texto de la licencia
76
+1504=Idioma (Language)
77
+1506=Consejos para el usuario
78
+1508=Acerca del sistema
79
+1509=Escala de la interfaz
80
+1510=Teclas de acceso rápido
81
+1511=Ajustes
82
+1520=Ahora
83
+1521=Cada día
84
+1522=Cada semana
85
+1523=Cada año
86
+1524=Nunca
87
+1590=Pequeño
88
+1591=Normal
89
+1592=Grande
90
+1593=Forzar HiDPI 2X
91
+1701=Salir de sView con escape
92
+1702=No salir
93
+1703=Con un clic
94
+1704=Con doble clic
95
+1705=Modo de ventana con un clic
96
+1710=Ocultar la barra de navegación del sistema
97
+1711=Abrir el último archivo visto al iniciar
98
+1712=JPS/PNS ve intercambio orden
99
+2000=Elije el archivo de imagen para abrir
100
+2001=Elige el archivo de la imagen IZQUIERDA para abrir
101
+2002=Elije el archivo de la imagen DERECHA para abrir
102
+2003=Información de la imagen
103
+2004=No hay disponible información
104
+2005=Eliminación de archivo
105
+2006=¿Realmente deseas eliminar completamente este archivo?
106
+2007=Guardando metadatos del archivo
107
+2008=¿Realmente deseas guardar los metadatos al archivo?
108
+2009=Los metadatos solo se pueden guardar en archivos JPEG.
109
+2010=Elije la ubicación para guardar la instantánea
110
+2011=¡Nada para guardar!
111
+2012=¡Instantánea no disponible!
112
+2013=Asignar nueva tecla de acceso rápido para la acción\n<i>{0}</i>
113
+2014=En conflicto con: <i>{0}</i>
114
+3000=sView - Visor de imágenes
115
+3001=versión
116
+3002=El visor de imágenes te permite abrir imágenes estereoscópicas en formatos JPEG, PNG, MPO y muchos más.\n © {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}\n\nEste programa se distribuye bajo licencia GPL 3.0
117
+3003=Hay disponible una nueva versión de sView en el sitio oficial: www.sview.ru.\nPor favor, actualiza el programa.
118
+3004=Información del sistema
119
+4000=Cerrar
120
+4001=Cancelar
121
+4006=Guardar
122
+4007=Eliminar
123
+4008=Predeterminado
124
+4009=Predeterminados
125
+4010=Asignar
126
+5000=[izquierdo]
127
+5001=[derecho]
128
+5002=Nombre de archivo
129
+5003=Dimensiones
130
+5004=Tiempo de carga
131
+5005=ms
132
+5006=Relación de pixeles
133
+5007=Formato de píxel
134
+5008=(no almacenado en los metadatos)
135
+5009=(no coincide con los metadatos)
136
+5011=(no almacenado en los metadatos,\npero detectado en el nombre de archivo)
137
+5012=Modelo de color
138
+5100=Comentario JPEG
139
+5101=Comentario JPS
140
+5200=Marca de la cámara
141
+5201=Modelo de la cámara
142
+5202=Comentario del usuario
143
+5203=Marca de tiempo de la imagen
144
+6000=Cambiar entre pantalla completa/ventana
145
+6001=Mostrar/ocultar medidor de FPS
146
+6002=Formato estéreo: Automático
147
+6003=Formato estéreo: Mono
148
+6004=Formato estéreo: Sobre/bajo
149
+6005=Formato estéreo: En paralelo
150
+6006=Mostrar información del archivo
151
+6007=Lista de reproducción: Ir al primer elemento
152
+6008=Lista de reproducción: Ir al último elemento
153
+6009=Lista de reproducción: Ir al anterior elemento
154
+6010=Lista de reproducción: Ir al siguiente elemento
155
+6011=Lista de reproducción: Iniciar/Detener presentación
156
+6012=Guardar en formato PNG
157
+6013=Guardar en formato JPEG
158
+6014=Guardar metadatos del archivo
159
+6015=Eliminar el archivo del sistema de archivos
160
+6016=Restablecer el ajuste de la imagen
161
+6017=Restablecer la posición de la imagen
162
+6018=Cambiar izquierdo/derecho
163
+6019=Corrección gamma: disminuir
164
+6020=Corrección gamma: aumentar
165
+6021=Separación DX: disminuir
166
+6022=Separación DX: aumentar
167
+6023=Separación DY: disminuir
168
+6024=Separación DY: aumentar
169
+6025=Separación angular: disminuir
170
+6026=Separación angular: aumentar
171
+6027=Rotar 90° a la izquierda
172
+6028=Rotar 90° a la derecha
173
+6029=Rotar a la izquierda
174
+6030=Rotar a la derecha
175
+6031=Seleccionar el siguiente modo de visualización
176
+6032=Barrido: navegar hacia la izquierda
177
+6033=Barrido: navegar hacia la derecha
178
+6034=Barrido: navegar hacia arriba
179
+6035=Barrido: navegar hacia abajo
180
+6036=Escala: aumentar
181
+6037=Escala: reducir
182
+6038=Rotación Y: izquierda
183
+6039=Rotación Y: derecha
184
+6040=Rotación X: arriba
185
+6041=Rotación X: abajo
186
+6042=Activar/Desactivar modo panorámico
187
+6043=Mostrar/ocultar GUI
188
sview-17_04.tar.gz/StMoviePlayer/StMovieOpenDialog.cpp -> sview-20_08.tar.gz/StMoviePlayer/StMovieOpenDialog.cpp Changed
111
 
1
@@ -74,18 +74,42 @@
2
 }
3
 
4
 void StMovieOpenDialog::setPaths(const StString& thePathLeft,
5
-                                 const StString& thePathRight) {
6
+                                 const StString& thePathRight,
7
+                                 const StMovieOpenDialog::DialogState theMode) {
8
     StMutexAuto aLock(myMutex);
9
     if(myState != StMovieOpenDialog::Dialog_Inactive) {
10
         return;
11
     }
12
 
13
-    myPathVideoL = thePathLeft;
14
-    myPathVideoR = thePathRight;
15
+    myPathVideoL.clear();
16
+    myPathVideoR.clear();
17
     myPathAudio.clear();
18
     myPathSubs .clear();
19
-    if(!myPathVideoL.isEmpty()) {
20
-        myState = StMovieOpenDialog::Dialog_HasFiles;
21
+    switch(theMode) {
22
+        case Dialog_Audio: {
23
+            myPathAudio = thePathLeft;
24
+            if(!myPathAudio.isEmpty()) {
25
+                myState = StMovieOpenDialog::Dialog_HasFiles;
26
+            }
27
+            break;
28
+        }
29
+        case Dialog_Subtitles: {
30
+            myPathSubs = thePathLeft;
31
+            if(!myPathSubs.isEmpty()) {
32
+                myState = StMovieOpenDialog::Dialog_HasFiles;
33
+            }
34
+            break;
35
+        }
36
+        case Dialog_SingleMovie:
37
+        case Dialog_DoubleMovie:
38
+        default: {
39
+            myPathVideoL = thePathLeft;
40
+            myPathVideoR = thePathRight;
41
+            if(!myPathVideoL.isEmpty()) {
42
+                myState = StMovieOpenDialog::Dialog_HasFiles;
43
+            }
44
+            break;
45
+        }
46
     }
47
 }
48
 
49
@@ -101,28 +125,36 @@
50
     myPathAudio .clear();
51
     myPathSubs  .clear();
52
 
53
-    StString aTitle;
54
-    const StMIMEList* aMimeList = &myPlugin->myVideo->getMimeListVideo();
55
+    StOpenFileName anOpenInfo;
56
+    anOpenInfo.Folder = myFolder;
57
     switch(myState) {
58
         case Dialog_DoubleMovie:
59
-            aTitle = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_LEFT);
60
+            anOpenInfo.Title = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_LEFT);
61
+            anOpenInfo.Filter = myPlugin->myVideo->getMimeListVideo();
62
+            anOpenInfo.FilterTitle = "Video Files";
63
             break;
64
         case Dialog_Audio:
65
-            aTitle    = "Choose audio file to attach";
66
-            aMimeList = &myPlugin->myVideo->getMimeListAudio();
67
+            anOpenInfo.Title = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_AUDIO);
68
+            anOpenInfo.Filter = myPlugin->myVideo->getMimeListAudio();
69
+            anOpenInfo.FilterTitle = "Audio Files";
70
             break;
71
         case Dialog_Subtitles:
72
-            aTitle    = "Choose subtitles file to attach";
73
-            aMimeList = &myPlugin->myVideo->getMimeListSubtitles();
74
+            anOpenInfo.Title = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_SUBTITLES);
75
+            anOpenInfo.Filter = myPlugin->myVideo->getMimeListSubtitles();
76
+            anOpenInfo.FilterTitle = "Subtitle Files";
77
             break;
78
         case Dialog_SingleMovie:
79
         default:
80
-            aTitle = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_FILE);
81
+            anOpenInfo.Title = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_FILE);
82
+            anOpenInfo.Filter = myPlugin->myVideo->getMimeListVideo();
83
+            anOpenInfo.FilterTitle = "Video Files";
84
+            anOpenInfo.ExtraFilter = myPlugin->myVideo->getMimeListImages();
85
+            anOpenInfo.ExtraFilterTitle = "Image files";
86
             break;
87
     }
88
 
89
-    StString aFilePath, aDummy;
90
-    if(!StFileNode::openFileDialog(myFolder, aTitle, *aMimeList, aFilePath, false)) {
91
+    StString aFilePath;
92
+    if(!StFileNode::openFileDialog(aFilePath, anOpenInfo, false)) {
93
         StMutexAuto aLock(myMutex);
94
         myState = StMovieOpenDialog::Dialog_Inactive;
95
         return;
96
@@ -130,10 +162,12 @@
97
 
98
     switch(myState) {
99
         case Dialog_DoubleMovie: {
100
-            aTitle =  myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_RIGHT);
101
+            anOpenInfo.Title = myPlugin->tr(StMoviePlayerStrings::DIALOG_OPEN_RIGHT);
102
+            StString aDummy;
103
             StFileNode::getFolderAndFile(aFilePath, myFolder, aDummy);
104
+            anOpenInfo.Folder = myFolder;
105
             myPathVideoL = aFilePath;
106
-            if(!StFileNode::openFileDialog(myFolder, aTitle, *aMimeList, myPathVideoR, false)) {
107
+            if(!StFileNode::openFileDialog(myPathVideoR, anOpenInfo, false)) {
108
                 StMutexAuto aLock(myMutex);
109
                 myState = StMovieOpenDialog::Dialog_Inactive;
110
                 return;
111
sview-17_04.tar.gz/StMoviePlayer/StMovieOpenDialog.h -> sview-20_08.tar.gz/StMoviePlayer/StMovieOpenDialog.h Changed
11
 
1
@@ -99,7 +99,8 @@
2
      * Set paths to open.
3
      */
4
     ST_LOCAL void setPaths(const StString& thePathLeft,
5
-                           const StString& thePathRight);
6
+                           const StString& thePathRight,
7
+                           const StMovieOpenDialog::DialogState theMode);
8
 
9
         private:
10
 
11
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayer.cpp -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayer.cpp Changed
709
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -75,6 +75,7 @@
9
     static const char ST_ARGUMENT_FILE_DEMO[]  = "demo";
10
     static const char ST_ARGUMENT_FILE_PAUSE[] = "pause";
11
     static const char ST_ARGUMENT_FILE_PAUSED[]= "paused";
12
+    static const char ST_ARGUMENT_FILE_SEEK[]  = "seek";
13
     static const char ST_ARGUMENT_MONITOR[]    = "monitorId";
14
     static const char ST_ARGUMENT_WINLEFT[]    = "windowLeft";
15
     static const char ST_ARGUMENT_WINTOP[]     = "windowTop";
16
@@ -91,7 +92,19 @@
17
 void StMoviePlayer::doPause(const StPauseEvent& theEvent) {
18
     StApplication::doPause(theEvent);
19
     saveAllParams();
20
-    if(!myVideo.isNull()) {
21
+    if(myVideo.isNull()) {
22
+        return;
23
+    }
24
+
25
+    // pause video but keep playing audio in background
26
+    StWinAttr anAttribs[] = {
27
+        StWinAttr_ToBlockSleepSystem,  (StWinAttr )0,
28
+        StWinAttr_ToBlockSleepDisplay, (StWinAttr )0,
29
+        StWinAttr_NULL
30
+    };
31
+    myWindow->getAttributes(anAttribs);
32
+    if(anAttribs[1] == (StWinAttr )0
33
+    || anAttribs[3] != (StWinAttr )0) {
34
         myVideo->pushPlayEvent(ST_PLAYEVENT_PAUSE);
35
     }
36
 }
37
@@ -107,6 +120,7 @@
38
     params.SubtitlesParser->setName(tr(MENU_SUBTITLES_PARSER));
39
     params.SubtitlesParser->defineOption(0, tr(MENU_SUBTITLES_PLAIN_TEXT));
40
     params.SubtitlesParser->defineOption(1, tr(MENU_SUBTITLES_LITE_HTML));
41
+    params.SubtitlesApplyStereo->setName(tr(MENU_SUBTITLES_STEREO));
42
     params.AudioAlHrtf->setName(stCString("Audio HRTF mixing"));
43
     params.AudioAlHrtf->defineOption(0, stCString("Auto"));
44
     params.AudioAlHrtf->defineOption(1, stCString("Forced ON"));
45
@@ -133,6 +147,7 @@
46
     params.SrcStereoFormat->setName(tr(MENU_MEDIA_SRC_FORMAT));
47
     params.ToShowPlayList->setName(tr(VIDEO_LIST));
48
     params.ToShowAdjustImage->setName(tr(MENU_VIEW_IMAGE_ADJUST));
49
+    params.ToSwapJPS->setName(tr(OPTION_SWAP_JPS));
50
     params.ToStickPanorama->setName(tr(MENU_VIEW_STICK_PANORAMA360));
51
     params.ToTrackHead->setName(tr(MENU_VIEW_TRACK_HEAD));
52
     params.ToTrackHeadAudio->setName(tr(MENU_VIEW_TRACK_HEAD_AUDIO));
53
@@ -140,9 +155,14 @@
54
     params.ToShowFps->setName(tr(MENU_FPS_METER));
55
     params.ToShowMenu->setName(stCString("Show main menu"));
56
     params.ToShowTopbar->setName(stCString("Show top toolbar"));
57
+    params.ToShowBottom->setName(stCString("Show seekbar"));
58
+    params.ToMixImagesVideos->setName(stCString("Mix images & videos"));
59
+    params.SlideShowDelay->setName(stCString("Slideshow delay"));
60
     params.IsMobileUI->setName(stCString("Mobile UI"));
61
+    params.IsExclusiveFullScreen->setName(tr(MENU_EXCLUSIVE_FULLSCREEN));
62
     params.IsVSyncOn->setName(tr(MENU_FPS_VSYNC));
63
     params.ToLimitFps->setName(tr(MENU_FPS_BOUND));
64
+    params.ToSmoothUploads->setName("Smooth texture uploading");
65
     params.StartWebUI->setName(stCString("Web UI start option"));
66
     params.StartWebUI->defineOption(WEBUI_OFF,  tr(MENU_MEDIA_WEBUI_OFF));
67
     params.StartWebUI->defineOption(WEBUI_ONCE, tr(MENU_MEDIA_WEBUI_ONCE));
68
@@ -164,7 +184,7 @@
69
 #if defined(_WIN32)
70
     const StCString aGpuAcc = stCString(" (DXVA2)");
71
 #elif defined(__APPLE__)
72
-    const StCString aGpuAcc = stCString(" (VDA)");
73
+    const StCString aGpuAcc = stCString(" (VideoToolbox)");
74
 #elif defined(__ANDROID__)
75
     const StCString aGpuAcc = stCString(""); //stCString(" (Android Media Codec)");
76
 #else
77
@@ -229,6 +249,7 @@
78
     params.SubtitlesParallax->setTolerance(0.1f);
79
     params.ToSearchSubs = new StBoolParamNamed(true, stCString("toSearchSubs"));
80
     params.SubtitlesParser = new StEnumParam(1, stCString("subsParser"));
81
+    params.SubtitlesApplyStereo = new StBoolParamNamed(true, stCString("subsApplyStereo"));
82
     params.AudioAlDevice = new StALDeviceParam();
83
     params.AudioAlHrtf   = new StEnumParam(0, stCString("alHrtfRequest"));
84
     params.AudioGain = new StFloat32Param( 0.0f, // sound is unattenuated
85
@@ -258,6 +279,8 @@
86
     params.ToShowPlayList->signals.onChanged = stSlot(this, &StMoviePlayer::doShowPlayList);
87
     params.ToShowAdjustImage = new StBoolParamNamed(false, stCString("showAdjustImage"));
88
     params.ToShowAdjustImage->signals.onChanged = stSlot(this, &StMoviePlayer::doShowAdjustImage);
89
+    params.ToSwapJPS  = new StBoolParamNamed(false, stCString("toSwapJPS"));
90
+    params.ToSwapJPS->signals.onChanged = stSlot(this, &StMoviePlayer::doChangeSwapJPS);
91
     params.ToStickPanorama  = new StBoolParamNamed(false, stCString("toStickPano360"));
92
     params.ToStickPanorama->signals.onChanged = stSlot(this, &StMoviePlayer::doChangeStickPano360);
93
     params.ToTrackHead      = new StBoolParamNamed(true,  stCString("toTrackHead"));
94
@@ -266,14 +289,25 @@
95
     params.ToShowFps   = new StBoolParamNamed(false, stCString("toShowFps"));
96
     params.ToShowMenu  = new StBoolParamNamed(true,  stCString("toShowMenu"));
97
     params.ToShowTopbar= new StBoolParamNamed(true,  stCString("toShowTopbar"));
98
+    params.ToShowBottom= new StBoolParamNamed(true,  stCString("toShowBottom"));
99
+    params.ToMixImagesVideos = new StBoolParamNamed(false,  stCString("toMixImagesVideos"));
100
+    params.ToMixImagesVideos->signals.onChanged = stSlot(this, &StMoviePlayer::doChangeMixImagesVideos);
101
+    params.SlideShowDelay = new StFloat32Param(4.0f, stCString("slideShowDelay2"));
102
+    params.SlideShowDelay->setMinMaxValues(1.0f, 10.0f);
103
+    params.SlideShowDelay->setDefValue(4.0f);
104
+    params.SlideShowDelay->setStep(1.0f);
105
+    params.SlideShowDelay->setTolerance(0.1f);
106
+    params.SlideShowDelay->setFormat(stCString("%01.1f s"));
107
     params.IsMobileUI  = new StBoolParamNamed(StWindow::isMobile(), stCString("isMobileUI"));
108
     params.IsMobileUI->signals.onChanged = stSlot(this, &StMoviePlayer::doChangeMobileUI);
109
     params.IsMobileUISwitch = new StBoolParam(params.IsMobileUI->getValue());
110
     params.IsMobileUISwitch->signals.onChanged = stSlot(this, &StMoviePlayer::doScaleHiDPI);
111
+    params.IsExclusiveFullScreen = new StBoolParamNamed(false, stCString("isExclusiveFullScreen"));
112
     params.IsVSyncOn   = new StBoolParamNamed(true, stCString("vsync"));
113
     params.IsVSyncOn->signals.onChanged = stSlot(this, &StMoviePlayer::doSwitchVSync);
114
     StApplication::params.VSyncMode->setValue(StGLContext::VSync_ON);
115
     params.ToLimitFps       = new StBoolParamNamed(true, stCString("toLimitFps"));
116
+    params.ToSmoothUploads  = new StBoolParamNamed(true, stCString("toSmoothUploads"));
117
     params.StartWebUI       = new StEnumParam(WEBUI_OFF, stCString("webuiOn"));
118
     params.ToPrintWebErrors = new StBoolParamNamed(true,  stCString("webuiShowErrors"));
119
     params.IsLocalWebUI     = new StBoolParamNamed(false, stCString("isLocalWebUI"));
120
@@ -322,17 +356,23 @@
121
     mySettings->loadParam (params.SubtitlesSize);
122
     mySettings->loadParam (params.SubtitlesParallax);
123
     mySettings->loadParam (params.SubtitlesParser);
124
+    mySettings->loadParam (params.SubtitlesApplyStereo);
125
     mySettings->loadParam (params.ToSearchSubs);
126
 
127
     myToCheckPoorOrient = !mySettings->loadParam(params.ToTrackHead);
128
+    mySettings->loadParam (params.ToSwapJPS);
129
     mySettings->loadParam (params.ToStickPanorama);
130
     mySettings->loadParam (params.ToTrackHeadAudio);
131
     mySettings->loadParam (params.ToForceBFormat);
132
     mySettings->loadParam (params.AudioAlHrtf);
133
     mySettings->loadParam (params.ToShowFps);
134
+    mySettings->loadParam (params.SlideShowDelay);
135
+    mySettings->loadParam (params.ToMixImagesVideos);
136
     mySettings->loadParam (params.IsMobileUI);
137
+    mySettings->loadParam (params.IsExclusiveFullScreen);
138
     mySettings->loadParam (params.IsVSyncOn);
139
     mySettings->loadParam (params.ToLimitFps);
140
+    mySettings->loadParam (params.ToSmoothUploads);
141
     mySettings->loadParam (params.UseGpu);
142
     mySettings->loadParam (params.UseOpenJpeg);
143
 
144
@@ -395,6 +435,9 @@
145
     anAction = new StActionBool(stCString("DoShowFPS"), params.ToShowFps);
146
     addAction(Action_ShowFps, anAction, ST_VK_F12);
147
 
148
+    anAction = new StActionIntSlot(stCString("DoShowGUI"), stSlot(this, &StMoviePlayer::doShowHideGUI), 0);
149
+    addAction(Action_ShowGUI, anAction, ST_VK_TILDE);
150
+
151
     anAction = new StActionIntValue(stCString("DoSrcAuto"), params.SrcStereoFormat, StFormat_AUTO);
152
     addAction(Action_SrcAuto, anAction, ST_VK_A);
153
 
154
@@ -500,6 +543,23 @@
155
 
156
     anAction = new StActionIntSlot(stCString("DoPanoramaOnOff"), stSlot(this, &StMoviePlayer::doPanoramaOnOff), 0);
157
     addAction(Action_PanoramaOnOff, anAction, ST_VK_P);
158
+
159
+    {
160
+    anAction = new StActionIntSlot(stCString("DoOutStereoNormal"), stSlot(this, &StMoviePlayer::doSetStereoOutput), StGLImageRegion::MODE_STEREO);
161
+    addAction(Action_OutStereoNormal, anAction);
162
+
163
+    anAction = new StActionIntSlot(stCString("DoOutStereoLeftView"), stSlot(this, &StMoviePlayer::doSetStereoOutput), StGLImageRegion::MODE_ONLY_LEFT);
164
+    addAction(Action_OutStereoLeftView, anAction);
165
+
166
+    anAction = new StActionIntSlot(stCString("DoOutStereoRightView"), stSlot(this, &StMoviePlayer::doSetStereoOutput), StGLImageRegion::MODE_ONLY_RIGHT);
167
+    addAction(Action_OutStereoRightView, anAction);
168
+
169
+    anAction = new StActionIntSlot(stCString("DoOutStereoParallelPair"), stSlot(this, &StMoviePlayer::doSetStereoOutput), StGLImageRegion::MODE_PARALLEL);
170
+    addAction(Action_OutStereoParallelPair, anAction);
171
+
172
+    anAction = new StActionIntSlot(stCString("DoOutStereoCrossEyed"), stSlot(this, &StMoviePlayer::doSetStereoOutput), StGLImageRegion::MODE_CROSSYED);
173
+    addAction(Action_OutStereoCrossEyed, anAction);
174
+    }
175
 }
176
 
177
 bool StMoviePlayer::resetDevice() {
178
@@ -544,6 +604,7 @@
179
         mySettings->saveParam (params.SubtitlesSize);
180
         mySettings->saveParam (params.SubtitlesParallax);
181
         mySettings->saveParam (params.SubtitlesParser);
182
+        mySettings->saveParam (params.SubtitlesApplyStereo);
183
         mySettings->saveParam (params.ToSearchSubs);
184
         mySettings->saveParam (params.TargetFps);
185
         mySettings->saveString(params.AudioAlDevice->getKey(), params.AudioAlDevice->getUtfTitle());
186
@@ -557,14 +618,19 @@
187
         mySettings->saveParam (params.ToShowPlayList);
188
         mySettings->saveParam (params.ToShowAdjustImage);
189
 
190
+        mySettings->saveParam (params.ToSwapJPS);
191
         mySettings->saveParam (params.ToStickPanorama);
192
         mySettings->saveParam (params.ToTrackHead);
193
         mySettings->saveParam (params.ToTrackHeadAudio);
194
         mySettings->saveParam (params.ToForceBFormat);
195
         mySettings->saveParam (params.ToShowFps);
196
+        mySettings->saveParam (params.SlideShowDelay);
197
+        mySettings->saveParam (params.ToMixImagesVideos);
198
         mySettings->saveParam (params.IsMobileUI);
199
+        mySettings->saveParam (params.IsExclusiveFullScreen);
200
         mySettings->saveParam (params.IsVSyncOn);
201
         mySettings->saveParam (params.ToLimitFps);
202
+        mySettings->saveParam (params.ToSmoothUploads);
203
         mySettings->saveParam (params.UseGpu);
204
         mySettings->saveParam (params.UseOpenJpeg);
205
         if(!params.IsLocalWebUI->getValue()) {
206
@@ -650,6 +716,12 @@
207
     }
208
 
209
     myGUI->stglInit();
210
+    StRectF_t aFrustL, aFrustR;
211
+    if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
212
+        myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
213
+    } else {
214
+        myGUI->changeCamera()->resetCustomProjection();
215
+    }
216
     myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
217
 
218
     for(size_t anIter = 0; anIter < myGUI->myImage->getActions().size(); ++anIter) {
219
@@ -690,7 +762,9 @@
220
         return;
221
     }
222
 
223
+    const bool isReadOnly = StFileNode::isFileReadOnly(myFileToDelete->getPath());
224
     const StString aText = myLangMap->getValue(StMoviePlayerStrings::DIALOG_DELETE_FILE_QUESTION)
225
+                         + (isReadOnly ? "\nWARNING! The file is READ ONLY!" : "")
226
                          + "\n" + myFileToDelete->getPath();
227
 
228
     StGLMessageBox* aDialog = new StGLMessageBox(myGUI.access(), myLangMap->getValue(StMoviePlayerStrings::DIALOG_DELETE_FILE_TITLE),
229
@@ -706,6 +780,7 @@
230
         return;
231
     }
232
 
233
+    StFileNode::removeReadOnlyFlag(myFileToDelete->getPath());
234
     myVideo->doRemovePhysically(myFileToDelete);
235
     myFileToDelete.nullify();
236
 }
237
@@ -824,8 +899,11 @@
238
         myVideo->params.UseOpenJpeg  = params.UseOpenJpeg;
239
         myVideo->params.ToSearchSubs = params.ToSearchSubs;
240
         myVideo->params.ToTrackHeadAudio = params.ToTrackHeadAudio;
241
+        myVideo->params.SlideShowDelay = params.SlideShowDelay;
242
+        myVideo->setSwapJPS(params.ToSwapJPS->getValue());
243
         myVideo->setStickPano360(params.ToStickPanorama->getValue());
244
         myVideo->setForceBFormat(params.ToForceBFormat->getValue());
245
+        doChangeMixImagesVideos(params.ToMixImagesVideos->getValue());
246
 
247
     #ifdef ST_HAVE_MONGOOSE
248
         doStartWebUI();
249
@@ -850,7 +928,7 @@
250
     // load this parameter AFTER video thread creation
251
     mySettings->loadParam(params.SrcStereoFormat);
252
 
253
-#if !defined(ST_NO_UPDATES_CHECK)
254
+#if defined(ST_UPDATES_CHECK)
255
     // read the current time
256
     time_t aRawtime;
257
     time(&aRawtime);
258
@@ -876,6 +954,7 @@
259
     StArgument anArgBenchmark  = theArguments[params.Benchmark->getKey()];
260
     StArgument anArgShowMenu   = theArguments[params.ToShowMenu->getKey()];
261
     StArgument anArgShowTopbar = theArguments[params.ToShowTopbar->getKey()];
262
+    StArgument anArgMixImages  = theArguments[params.ToMixImagesVideos->getKey()];
263
 
264
     StArgument anArgFullscreen = theArguments[params.IsFullscreen->getKey()];
265
     StArgument anArgMonitor    = theArguments[ST_ARGUMENT_MONITOR];
266
@@ -941,6 +1020,9 @@
267
     if(anArgShowTopbar.isValid()) {
268
         params.ToShowTopbar->setValue(!anArgShowTopbar.isValueOff());
269
     }
270
+    if(anArgMixImages.isValid()) {
271
+        params.ToMixImagesVideos->setValue(!anArgMixImages.isValueOff());
272
+    }
273
 }
274
 
275
 bool StMoviePlayer::open() {
276
@@ -979,6 +1061,8 @@
277
             doOpenRecent(0); // open last opened file
278
             if(isPaused) {
279
                 myVideo->pushPlayEvent(ST_PLAYEVENT_PAUSE);
280
+            } else if(!anArgLast.isValid() && !anArgPause.isValid() && !anArgPaused.isValid()) {
281
+                myVideo->pushPlayEvent(ST_PLAYEVENT_PAUSE);
282
             }
283
         }
284
         return true;
285
@@ -988,8 +1072,13 @@
286
     myPlayList->clear();
287
 
288
     //StArgument argFile1     = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE + 1]; // playlist?
289
-    StArgument argFileLeft  = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE_LEFT];
290
-    StArgument argFileRight = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE_RIGHT];
291
+    const StArgument argFileLeft  = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE_LEFT];
292
+    const StArgument argFileRight = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE_RIGHT];
293
+    const StArgument anArgSeek    = myOpenFileInfo->getArgumentsMap()[ST_ARGUMENT_FILE_SEEK];
294
+    if(anArgSeek.isValid()) {
295
+        StCLocale aCLocale;
296
+        mySeekOnLoad = stStringToDouble(anArgSeek.getValue().toCString(), aCLocale);
297
+    }
298
     if(argFileLeft.isValid() && argFileRight.isValid()) {
299
         // meta-file
300
         const size_t aRecent = myPlayList->findRecent(argFileLeft.getValue(), argFileRight.getValue());
301
@@ -1002,19 +1091,50 @@
302
         }
303
         myPlayList->addOneFile(argFileLeft.getValue(), argFileRight.getValue());
304
     } else if(!anOpenMIME.isEmpty()) {
305
+        // handle URI with #t=SECONDS tail
306
+        StString aFilePath = myOpenFileInfo->getPath();
307
+        StHandle< StArrayList<StString> > anUriParams = aFilePath.split('#', 2);
308
+        if(anUriParams->size() == 2) {
309
+            aFilePath = anUriParams->getFirst();
310
+            StString aParams = anUriParams->getLast();
311
+            if(aParams.isStartsWith(stCString("t="))) {
312
+                StCLocale aCLocale;
313
+                mySeekOnLoad = stStringToDouble(aParams.toCString() + 2, aCLocale);
314
+            }
315
+        }
316
+
317
         // create just one-file playlist
318
         myPlayList->addOneFile(myOpenFileInfo->getPath(), anOpenMIME);
319
     } else {
320
+        // handle URI with #t=SECONDS tail
321
+        StString aFilePath = myOpenFileInfo->getPath();
322
+        double aSeekPos = -1.0;
323
+        StHandle< StArrayList<StString> > anUriParams = aFilePath.split('#', 2);
324
+        if(anUriParams->size() == 2) {
325
+            aFilePath = anUriParams->getFirst();
326
+            StString aParams = anUriParams->getLast();
327
+            if(aParams.isStartsWith(stCString("t="))) {
328
+                StCLocale aCLocale;
329
+                aSeekPos = stStringToDouble(aParams.toCString() + 2, aCLocale);
330
+            }
331
+        }
332
+
333
         // create playlist from file's folder
334
-        const size_t aRecent = myPlayList->findRecent(myOpenFileInfo->getPath());
335
+        const size_t aRecent = myPlayList->findRecent(aFilePath);
336
         if(aRecent != size_t(-1)) {
337
             doOpenRecent(aRecent);
338
+            if(aSeekPos >= 0.0) {
339
+                mySeekOnLoad = aSeekPos;
340
+            }
341
             if(isPaused) {
342
                 myVideo->pushPlayEvent(ST_PLAYEVENT_PAUSE);
343
             }
344
             return true;
345
         }
346
-        myPlayList->open(myOpenFileInfo->getPath());
347
+        if(aSeekPos >= 0.0) {
348
+            mySeekOnLoad = aSeekPos;
349
+        }
350
+        myPlayList->open(aFilePath);
351
     }
352
 
353
     if(!myPlayList->isEmpty()) {
354
@@ -1039,6 +1159,12 @@
355
     if(toMobileGui != wasMobileGui) {
356
         doChangeMobileUI(params.IsMobileUI->getValue());
357
     } else {
358
+        StRectF_t aFrustL, aFrustR;
359
+        if(myWindow->getCustomProjection(aFrustL, aFrustR)) {
360
+            myGUI->changeCamera()->setCustomProjection(aFrustL, aFrustR);
361
+        } else {
362
+            myGUI->changeCamera()->resetCustomProjection();
363
+        }
364
         myGUI->stglResize(myWindow->stglViewport(ST_WIN_MASTER), myWindow->getMargins(), (float )myWindow->stglAspectRatio());
365
     }
366
 }
367
@@ -1134,20 +1260,8 @@
368
 }
369
 
370
 void StMoviePlayer::doGesture(const StGestureEvent& theEvent) {
371
-    if(myGUI.isNull()
372
-    || myGUI->myImage == NULL) {
373
-        return;
374
-    }
375
-
376
-    for(StGLWidget *aChildIter(myGUI->getChildren()->getLast()), *aChildActive(NULL); aChildIter != NULL;) {
377
-        aChildActive = aChildIter;
378
-        aChildIter   = aChildIter->getPrev();
379
-        if(aChildActive->isVisibleAndPointIn(myGUI->getCursorZo())) {
380
-            if(aChildActive == myGUI->myImage) {
381
-                myGUI->myImage->doGesture(theEvent);
382
-            }
383
-            break;
384
-        }
385
+    if(!myGUI.isNull()) {
386
+        myGUI->doGesture(theEvent);
387
     }
388
 }
389
 
390
@@ -1237,11 +1351,30 @@
391
         return;
392
     }
393
 
394
+    // handle URI with #t=SECONDS tail
395
+    double aSeekPos = -1.0;
396
+    StHandle< StArrayList<StString> > anUriParams = aText.split('#', 2);
397
+    if(anUriParams->size() == 2) {
398
+        aText = anUriParams->getFirst();
399
+        StString aParams = anUriParams->getLast();
400
+        if(aParams.isStartsWith(stCString("t="))) {
401
+            StCLocale aCLocale;
402
+            aSeekPos = stStringToDouble(aParams.toCString() + 2, aCLocale);
403
+        }
404
+    }
405
+
406
     const size_t aRecent = myPlayList->findRecent(aText);
407
     if(aRecent != size_t(-1)) {
408
         doOpenRecent(aRecent);
409
+        if(aSeekPos >= 0.0) {
410
+            mySeekOnLoad = aSeekPos;
411
+        }
412
         return;
413
     }
414
+
415
+    if(aSeekPos >= 0.0) {
416
+        mySeekOnLoad = aSeekPos;
417
+    }
418
     myPlayList->open(aText);
419
     if(!myPlayList->isEmpty()) {
420
         doUpdateStateLoading();
421
@@ -1292,19 +1425,29 @@
422
             return;
423
         }
424
 
425
+        if(!myPlayList->checkExtension(aFile1)
426
+         && myVideo->getMimeListImages().checkExtension(anExt1)) {
427
+            // redirect to StMoviePlayer
428
+            myOpenFileOtherApp = new StOpenInfo();
429
+            StArgumentsMap anArgs;
430
+            anArgs.add(StArgument("in", "image"));
431
+            myOpenFileOtherApp->setArgumentsMap(anArgs);
432
+            myOpenFileOtherApp->setPath(aFile1);
433
+            exit(0);
434
+            return;
435
+        }
436
+
437
         // just open the path
438
-        //if(myPlayList->checkExtension(aFile1)) {
439
-            const size_t aRecent = myPlayList->findRecent(aFile1);
440
-            if(aRecent != size_t(-1)) {
441
-                doOpenRecent(aRecent);
442
-                return;
443
-            }
444
+        const size_t aRecent = myPlayList->findRecent(aFile1);
445
+        if(aRecent != size_t(-1)) {
446
+            doOpenRecent(aRecent);
447
+            return;
448
+        }
449
 
450
-            myPlayList->open(aFile1);
451
-            doUpdateStateLoading();
452
-            myVideo->pushPlayEvent(ST_PLAYEVENT_RESUME);
453
-            myVideo->doLoadNext();
454
-        //}
455
+        myPlayList->open(aFile1);
456
+        doUpdateStateLoading();
457
+        myVideo->pushPlayEvent(ST_PLAYEVENT_RESUME);
458
+        myVideo->doLoadNext();
459
         return;
460
     } else if(theEvent.NbFiles == 2
461
           && !StFolder::isFolder(aFile2)
462
@@ -1343,6 +1486,7 @@
463
             myPlayList->addOneFile(aPath, StMIME());
464
         }
465
     }
466
+
467
     doUpdateStateLoading();
468
     myVideo->pushPlayEvent(ST_PLAYEVENT_RESUME);
469
     myVideo->doLoadNext();
470
@@ -1399,8 +1543,19 @@
471
             myPlayList->clear();
472
             myPlayList->addOneFile(myOpenDialog->getPathLeft(), myOpenDialog->getPathRight());
473
         } else {
474
-            aFilePath = myOpenDialog->getPathLeft();
475
-            myPlayList->open(myOpenDialog->getPathLeft());
476
+            if(!myPlayList->checkExtension(myOpenDialog->getPathLeft())
477
+             && myVideo->getMimeListImages().checkExtension(StFileNode::getExtension(myOpenDialog->getPathLeft()))) {
478
+                // redirect to StImageViewer
479
+                myOpenFileOtherApp = new StOpenInfo();
480
+                StArgumentsMap anArgs;
481
+                anArgs.add(StArgument("in", "image"));
482
+                myOpenFileOtherApp->setArgumentsMap(anArgs);
483
+                myOpenFileOtherApp->setPath(myOpenDialog->getPathLeft());
484
+                exit(0);
485
+            } else {
486
+                aFilePath = myOpenDialog->getPathLeft();
487
+                myPlayList->open(myOpenDialog->getPathLeft());
488
+            }
489
         }
490
 
491
         doUpdateStateLoading();
492
@@ -1508,6 +1663,9 @@
493
     }
494
     myWindow->setStereoOutput(hasStereoSource);
495
 
496
+    const double aDispMaxFps = myWindow->getMaximumTargetFps();
497
+    double aTargetFps = myVideo->getAverFps();
498
+    int aMaxUploadFrames = int((double(aDispMaxFps) + 0.1) / stMax(aTargetFps, 1.0));
499
     if(params.Benchmark->getValue()
500
     || !params.ToLimitFps->getValue()) {
501
         // do not limit FPS
502
@@ -1515,25 +1673,39 @@
503
     } else if(params.TargetFps->getValue() >= 1
504
            && params.TargetFps->getValue() <= 3) {
505
         // set rendering FPS to 2x averageFPS
506
-        double aTargetFps = myVideo->getAverFps();
507
+        const bool toTrackOrientation = myWindow->toTrackOrientation();
508
         if(aTargetFps < 17.0
509
         || aTargetFps > 120.0) {
510
             aTargetFps = 0.0;
511
         } else if(aTargetFps < 40.0) {
512
+            if(!toTrackOrientation) {
513
+                aMaxUploadFrames = 2; // maximum 2 frames to upload single frame
514
+            }
515
             aTargetFps *= double(params.TargetFps->getValue());
516
+        } else {
517
+            if(!toTrackOrientation) {
518
+                aMaxUploadFrames = 1; // uploads should be done within single frame
519
+            }
520
         }
521
 
522
-        if(myWindow->toTrackOrientation()) {
523
+        if(toTrackOrientation) {
524
             // do not limit FPS within head-tracking mode
525
             aTargetFps = 0.0;
526
+        } else if(aTargetFps > aDispMaxFps) {
527
+            aTargetFps = 0.0;
528
         }
529
 
530
         myWindow->setTargetFps(aTargetFps);
531
     } else {
532
         // set rendering FPS to set value in settings
533
         myWindow->setTargetFps(double(params.TargetFps->getValue()));
534
+        aMaxUploadFrames = 1; // uploads should be done within single frame
535
     }
536
 
537
+    if(!params.ToSmoothUploads->getValue()) {
538
+        aMaxUploadFrames = 1;
539
+    }
540
+    myVideo->getTextureQueue()->getUploadParams().MaxUploadIterations = stMax(stMin(aMaxUploadFrames, 3), 1);
541
 }
542
 
543
 void StMoviePlayer::doUpdateOpenALDeviceList(const size_t ) {
544
@@ -1713,6 +1885,14 @@
545
     }
546
 }
547
 
548
+void StMoviePlayer::doSwitchViewMode(const int32_t theMode) {
549
+    if(myVideo.isNull()) {
550
+        return;
551
+    }
552
+
553
+    myVideo->setTheaterMode(theMode == StViewSurface_Theater);
554
+}
555
+
556
 void StMoviePlayer::doPanoramaOnOff(const size_t ) {
557
     if(myVideo.isNull()) {
558
         return;
559
@@ -1734,9 +1914,7 @@
560
     StPanorama aPano = st::probePanorama(aParams->StereoFormat,
561
                                          aParams->Src1SizeX, aParams->Src1SizeY,
562
                                          aParams->Src2SizeX, aParams->Src2SizeY);
563
-    myGUI->myImage->params.ViewMode->setValue(aPano == StPanorama_Cubemap6_1 || aPano == StPanorama_Cubemap3_2
564
-                                            ? StViewSurface_Cubemap
565
-                                            : StViewSurface_Sphere);
566
+    myGUI->myImage->params.ViewMode->setValue(StStereoParams::getViewSurfaceForPanoramaSource(aPano, true));
567
 }
568
 
569
 void StMoviePlayer::doChangeStickPano360(const bool ) {
570
@@ -1747,6 +1925,14 @@
571
     myVideo->setStickPano360(params.ToStickPanorama->getValue());
572
 }
573
 
574
+void StMoviePlayer::doChangeSwapJPS(const bool ) {
575
+    if(myVideo.isNull()) {
576
+        return;
577
+    }
578
+
579
+    myVideo->setSwapJPS(params.ToSwapJPS->getValue());
580
+}
581
+
582
 void StMoviePlayer::doSwitchSrcFormat(const int32_t theSrcFormat) {
583
     myVideo->setStereoFormat(StFormat(theSrcFormat));
584
     double aDuration = 0.0;
585
@@ -1760,6 +1946,13 @@
586
     }
587
 }
588
 
589
+void StMoviePlayer::doSetStereoOutput(const size_t theMode) {
590
+    if(myVideo.isNull()) {
591
+        return;
592
+    }
593
+    myGUI->myImage->params.DisplayMode->setValue((int32_t )theMode);
594
+}
595
+
596
 void StMoviePlayer::doScaleGui(const int32_t ) {
597
     if(myGUI.isNull()) {
598
         return;
599
@@ -1778,6 +1971,22 @@
600
     myToRecreateMenu = true;
601
 }
602
 
603
+void StMoviePlayer::doChangeMixImagesVideos(const bool theToMix) {
604
+    if(myVideo.isNull()) {
605
+        return;
606
+    }
607
+    if(theToMix) {
608
+        StArrayList<StString> aMediaExt = myVideo->getMimeListVideo().getExtensionsList();
609
+        StArrayList<StString> anImgExt  = myVideo->getMimeListImages().getExtensionsList();
610
+        for(size_t anExtIter = 0; anExtIter < anImgExt.size(); ++anExtIter) {
611
+            aMediaExt.add(anImgExt.getValue(anExtIter));
612
+        }
613
+        myPlayList->setExtensions(aMediaExt);
614
+    } else {
615
+        myPlayList->setExtensions(myVideo->getMimeListVideo().getExtensionsList());
616
+    }
617
+}
618
+
619
 void StMoviePlayer::doLoaded() {
620
     myEventLoaded.set();
621
 }
622
@@ -1810,23 +2019,45 @@
623
     }
624
 }
625
 
626
+void StMoviePlayer::doShowHideGUI(const size_t ) {
627
+    const bool toShow = !params.ToShowMenu->getValue() || (!myGUI.isNull() && !myGUI->isVisibleGUI());
628
+    params.ToShowMenu->setValue(toShow);
629
+    params.ToShowTopbar->setValue(toShow);
630
+    params.ToShowBottom->setValue(toShow);
631
+    if(toShow && !myGUI.isNull()) {
632
+        myGUI->setVisibility(myWindow->getMousePos(), false, true);
633
+    }
634
+}
635
+
636
 void StMoviePlayer::doQuit(const size_t ) {
637
     StApplication::exit(0);
638
 }
639
 
640
 void StMoviePlayer::doOpen1FileFromGui(StHandle<StString> thePath) {
641
-    myOpenDialog->setPaths(*thePath, "");
642
+    myOpenDialog->setPaths(*thePath, "", StMovieOpenDialog::Dialog_SingleMovie);
643
+}
644
+
645
+void StMoviePlayer::doOpen1AudioFromGui(StHandle<StString> thePath) {
646
+    myOpenDialog->setPaths(*thePath, "", StMovieOpenDialog::Dialog_Audio);
647
+}
648
+
649
+void StMoviePlayer::doOpen1SubtitleFromGui(StHandle<StString> thePath) {
650
+    myOpenDialog->setPaths(*thePath, "", StMovieOpenDialog::Dialog_Subtitles);
651
 }
652
 
653
 void StMoviePlayer::doOpen1FileAction(const size_t ) {
654
     if(!myGUI.isNull() && (myWindow->isFullScreen() || myGUI->isMobile())) {
655
-        myGUI->doOpenFile(0);
656
+        myGUI->doOpenFile(StMovieOpenDialog::Dialog_SingleMovie);
657
         return;
658
     }
659
     myOpenDialog->openDialog(StMovieOpenDialog::Dialog_SingleMovie);
660
 }
661
 
662
 void StMoviePlayer::doOpen2Files(const size_t ) {
663
+    if(!myGUI.isNull() && (myWindow->isFullScreen() || myGUI->isMobile())) {
664
+        //myGUI->doOpenFile(StMovieOpenDialog::Dialog_DoubleMovie);
665
+        //return;
666
+    }
667
     myOpenDialog->openDialog(StMovieOpenDialog::Dialog_DoubleMovie);
668
 }
669
 
670
@@ -1858,10 +2089,18 @@
671
 }
672
 
673
 void StMoviePlayer::doAddAudioStream(const size_t ) {
674
+    if(!myGUI.isNull() && (myWindow->isFullScreen() || myGUI->isMobile())) {
675
+        myGUI->doOpenFile(StMovieOpenDialog::Dialog_Audio);
676
+        return;
677
+    }
678
     myOpenDialog->openDialog(StMovieOpenDialog::Dialog_Audio);
679
 }
680
 
681
 void StMoviePlayer::doAddSubtitleStream(const size_t ) {
682
+    if(!myGUI.isNull() && (myWindow->isFullScreen() || myGUI->isMobile())) {
683
+        myGUI->doOpenFile(StMovieOpenDialog::Dialog_Subtitles);
684
+        return;
685
+    }
686
     myOpenDialog->openDialog(StMovieOpenDialog::Dialog_Subtitles);
687
 }
688
 
689
@@ -1914,6 +2153,7 @@
690
 
691
 void StMoviePlayer::doFullscreen(const bool theIsFullscreen) {
692
     if(!myWindow.isNull()) {
693
+        myWindow->setAttribute(StWinAttr_ExclusiveFullScreen, params.IsExclusiveFullScreen->getValue());
694
         myWindow->setFullScreen(theIsFullscreen);
695
     }
696
 }
697
@@ -2007,6 +2247,11 @@
698
         const long aVol = stStringToLong(aQuery.toCString(), 10, aCLocale);
699
         params.AudioGain->setValue(volumeToGain(params.AudioGain, GLfloat(aVol) * 0.01f));
700
         aContent = "audio set volume...";
701
+    } else if(anURI.isEquals(stCString("/seek"))) {
702
+        StCLocale aCLocale;
703
+        const double aPosSec = stStringToDouble(aQuery.toCString(), aCLocale);
704
+        myVideo->pushPlayEvent(ST_PLAYEVENT_SEEK, aPosSec);
705
+        aContent = "seek to position...";
706
     } else if(anURI.isEquals(stCString("/fullscr_win"))) {
707
         invokeAction(Action_Fullscreen);
708
         aContent = "switch fullscreen/windowed...";
709
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayer.h -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayer.h Changed
87
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2007-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2007-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -124,11 +124,14 @@
9
     ST_LOCAL void doSubtitlesNext(size_t theDirection);
10
     ST_LOCAL void doSubtitlesCopy(size_t dummy = 0);
11
     ST_LOCAL void doFromClipboard(size_t dummy = 0);
12
+    ST_LOCAL void doShowHideGUI(const size_t dummy = 0);
13
 
14
     ST_LOCAL void doQuit(const size_t dummy = 0);
15
 
16
     ST_LOCAL void doFileNext();
17
     ST_LOCAL void doOpen1FileFromGui(StHandle<StString> thePath);
18
+    ST_LOCAL void doOpen1AudioFromGui(StHandle<StString> thePath);
19
+    ST_LOCAL void doOpen1SubtitleFromGui(StHandle<StString> thePath);
20
     ST_LOCAL void doOpen1FileAction(const size_t dummy = 0);
21
     ST_LOCAL void doOpen2Files(const size_t dummy = 0);
22
     ST_LOCAL void doSaveFileInfo(const size_t theToSave);
23
@@ -186,6 +189,7 @@
24
         StHandle<StFloat32Param>      SubtitlesParallax; //!< subtitles parallax
25
         StHandle<StBoolParamNamed>    ToSearchSubs;      //!< automatically search for additional subtitles/audio track files nearby video file
26
         StHandle<StEnumParam>         SubtitlesParser;   //!< subtitles parser
27
+        StHandle<StBoolParamNamed>    SubtitlesApplyStereo; //!<  apply stereoscopic format of video to image subtitles
28
         StHandle<StALDeviceParam>     AudioAlDevice;     //!< active OpenAL device
29
         StHandle<StEnumParam>         AudioAlHrtf;       //!< OpenAL HRTF flag
30
         StHandle<StFloat32Param>      AudioGain;         //!< volume factor
31
@@ -200,6 +204,7 @@
32
         StHandle<StEnumParam>         CheckUpdatesDays;  //!< days count between updates checks
33
         StHandle<StInt32ParamNamed>   LastUpdateDay;     //!< the last time update has been checked
34
         StHandle<StInt32ParamNamed>   SrcStereoFormat;   //!< source format
35
+        StHandle<StBoolParamNamed>    ToSwapJPS;         //!< swap JPS views order
36
         StHandle<StBoolParamNamed>    ToStickPanorama;   //!< force panorama input for all files
37
         StHandle<StBoolParamNamed>    ToTrackHead;       //!< enable/disable head-tracking
38
         StHandle<StBoolParamNamed>    ToTrackHeadAudio;  //!< enable/disable head-tracking for audio listener
39
@@ -209,9 +214,14 @@
40
         StHandle<StBoolParamNamed>    ToShowFps;         //!< display FPS meter
41
         StHandle<StBoolParamNamed>    ToShowMenu;        //!< show main menu
42
         StHandle<StBoolParamNamed>    ToShowTopbar;      //!< show topbar
43
+        StHandle<StBoolParamNamed>    ToShowBottom;      //!< show bottom (seekbar)
44
+        StHandle<StBoolParamNamed>    ToMixImagesVideos; //!< mix videos and images
45
+        StHandle<StFloat32Param>      SlideShowDelay;    //!< slideshow delay
46
         StHandle<StBoolParamNamed>    IsMobileUI;        //!< display mobile interface (user option)
47
         StHandle<StBoolParam>         IsMobileUISwitch;  //!< display mobile interface (actual value)
48
+        StHandle<StBoolParamNamed>    IsExclusiveFullScreen; //!< exclusive fullscreen mode
49
         StHandle<StBoolParamNamed>    ToLimitFps;        //!< limit CPU usage or not
50
+        StHandle<StBoolParamNamed>    ToSmoothUploads;   //!< smooth texture uploads
51
         StHandle<StBoolParamNamed>    IsVSyncOn;         //!< flag to use VSync
52
         StHandle<StEnumParam>         StartWebUI;        //!< to start Web UI or not
53
         StHandle<StBoolParamNamed>    ToPrintWebErrors;  //!< print Web UI starting errors
54
@@ -285,6 +295,7 @@
55
     ST_LOCAL void doScaleGui(const int32_t );
56
     ST_LOCAL void doChangeMobileUI(const bool );
57
     ST_LOCAL void doScaleHiDPI(const bool );
58
+    ST_LOCAL void doChangeMixImagesVideos(const bool );
59
     ST_LOCAL void doSwitchVSync(const bool theValue);
60
     ST_LOCAL void doSwitchAudioDevice(const int32_t theDevId);
61
     ST_LOCAL void doSwitchAudioAlHrtf(const int32_t theValue);
62
@@ -296,8 +307,11 @@
63
     ST_LOCAL void doSwitchLoopSingle(const bool theValue);
64
     ST_LOCAL void doFullscreen(const bool theIsFullscreen);
65
     ST_LOCAL void doSwitchSrcFormat(const int32_t theSrcFormat);
66
+    ST_LOCAL void doSetStereoOutput(const size_t theMode);
67
+    ST_LOCAL void doSwitchViewMode(const int32_t theMode);
68
     ST_LOCAL void doPanoramaOnOff(const size_t );
69
     ST_LOCAL void doChangeStickPano360(const bool );
70
+    ST_LOCAL void doChangeSwapJPS(const bool );
71
     ST_LOCAL void doSwitchAudioStream(const int32_t theStreamId);
72
     ST_LOCAL void doSwitchSubtitlesStream(const int32_t theStreamId);
73
     ST_LOCAL void doShowPlayList(const bool theToShow);
74
@@ -349,6 +363,12 @@
75
         Action_StereoParamsBegin,
76
         Action_StereoParamsEnd = Action_StereoParamsBegin + StGLImageRegion::ActionsNb - 1,
77
         Action_PanoramaOnOff,
78
+        Action_ShowGUI,
79
+        Action_OutStereoNormal,
80
+        Action_OutStereoLeftView,
81
+        Action_OutStereoRightView,
82
+        Action_OutStereoParallelPair,
83
+        Action_OutStereoCrossEyed,
84
     };
85
 
86
         private: //! @name Web UI methods
87
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayer.rc -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayer.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereoscopic Movie Player\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StMoviePlayer\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayerGUI.cpp -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayerGUI.cpp Changed
721
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -24,6 +24,7 @@
9
 
10
 #include "StVideo/StALContext.h"
11
 #include "StVideo/StVideo.h"
12
+#include "StMovieOpenDialog.h"
13
 
14
 #include <StCore/StSearchMonitors.h>
15
 #include <StImage/StImageFile.h>
16
@@ -61,6 +62,8 @@
17
 
18
 namespace {
19
 
20
+    static const float THE_VISIBILITY_IDLE_TIME = 2.0f;
21
+
22
     static const int DISPL_Y_REGION_UPPER  = 32;
23
     static const int DISPL_X_REGION_UPPER  = 32;
24
     static const int DISPL_X_REGION_BOTTOM = 52;
25
@@ -130,22 +133,22 @@
26
     const int      anIconStep = scale(48);
27
     aButtonMargins.extend(scale(8));
28
 
29
-    myPanelUpper = new StGLContainer(this, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), scale(4096), scale(128));
30
+    myPanelUpper = new StGLContainer(this, aLeft, aTop, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), scale(4096), scale(128));
31
 
32
     // append the textured buttons
33
-    myBtnOpen = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
34
+    myBtnOpen = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
35
     myBtnOpen->signals.onBtnClick.connect(myPlugin, &StMoviePlayer::doOpen1FileAction);
36
     myBtnOpen->setTexturePath(iconTexture(stCString("actionOpen"), anIconSize));
37
     myBtnOpen->setDrawShadow(true);
38
     myBtnOpen->changeMargins() = aButtonMargins;
39
 
40
-    myBtnInfo = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop);
41
+    myBtnInfo = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0);
42
     myBtnInfo->signals.onBtnClick += stSlot(myPlugin, &StMoviePlayer::doAboutFile);
43
     myBtnInfo->setTexturePath(iconTexture(stCString("actionInfo"),  anIconSize));
44
     myBtnInfo->setDrawShadow(true);
45
     myBtnInfo->changeMargins() = aButtonMargins;
46
 
47
-    StGLTextureButton* aSrcBtn = new StGLTextureButton(myPanelUpper, aLeft + (aBtnIter++) * anIconStep, aTop,
48
+    StGLTextureButton* aSrcBtn = new StGLTextureButton(myPanelUpper, (aBtnIter++) * anIconStep, 0,
49
                                                        StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT), StFormat_NB + 1);
50
     aSrcBtn->changeMargins() = aButtonMargins;
51
     aSrcBtn->signals.onBtnClick += stSlot(this, &StMoviePlayerGUI::doDisplayStereoFormatCombo);
52
@@ -172,7 +175,7 @@
53
     myBtnSwapLR = new StGLCheckboxTextured(myPanelUpper, myImage->params.SwapLR,
54
                                            iconTexture(stCString("actionSwapLROff"), anIconSize),
55
                                            iconTexture(stCString("actionSwapLROn"),  anIconSize),
56
-                                           aLeft + (aBtnIter++) * anIconStep, aTop,
57
+                                           (aBtnIter++) * anIconStep, 0,
58
                                            StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
59
     myBtnSwapLR->setDrawShadow(true);
60
     myBtnSwapLR->changeMargins() = aButtonMargins;
61
@@ -181,7 +184,7 @@
62
     myBtnPanorama = new StGLCheckboxTextured(myPanelUpper, aTrackedPano,
63
                                              iconTexture(stCString("actionPanoramaOff"), anIconSize),
64
                                              iconTexture(stCString("actionPanorama"),    anIconSize),
65
-                                             aLeft + (aBtnIter++) * anIconStep, aTop,
66
+                                             (aBtnIter++) * anIconStep, 0,
67
                                              StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
68
     myBtnPanorama->signals.onBtnClick += stSlot(this, &StMoviePlayerGUI::doPanoramaCombo);
69
     myBtnPanorama->setDrawShadow(true);
70
@@ -190,7 +193,7 @@
71
     myBtnAdjust = new StGLCheckboxTextured(myPanelUpper, myPlugin->params.ToShowAdjustImage,
72
                                            iconTexture(stCString("actionColorAdjustOff"), anIconSize),
73
                                            iconTexture(stCString("actionColorAdjust"),    anIconSize),
74
-                                           aLeft + (aBtnIter++) * anIconStep, aTop,
75
+                                           (aBtnIter++) * anIconStep, 0,
76
                                            StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
77
     myBtnAdjust->setDrawShadow(true);
78
     myBtnAdjust->changeMargins() = aButtonMargins;
79
@@ -200,7 +203,7 @@
80
     myBtnSubs = new StGLCheckboxTextured(myPanelUpper, aTrackedSubs,
81
                                          iconTexture(stCString("actionStreamSubtitlesOff"), anIconSize),
82
                                          iconTexture(stCString("actionStreamSubtitles"),    anIconSize),
83
-                                         (aNbBtnRight++) * (-anIconStep) - aLeft, aTop,
84
+                                         (aNbBtnRight++) * (-anIconStep), 0,
85
                                          StGLCorner(ST_VCORNER_TOP, ST_HCORNER_RIGHT));
86
     myBtnSubs->signals.onBtnClick = stSlot(this, &StMoviePlayerGUI::doSubtitlesStreamsCombo);
87
     myBtnSubs->setDrawShadow(true);
88
@@ -210,7 +213,7 @@
89
     myBtnAudio = new StGLCheckboxTextured(myPanelUpper, aTrackedAudio,
90
                                           iconTexture(stCString("actionStreamAudioOff"), anIconSize),
91
                                           iconTexture(stCString("actionStreamAudio"),    anIconSize),
92
-                                          (aNbBtnRight++) * (-anIconStep) - aLeft, aTop,
93
+                                          (aNbBtnRight++) * (-anIconStep), 0,
94
                                           StGLCorner(ST_VCORNER_TOP, ST_HCORNER_RIGHT));
95
     myBtnAudio->signals.onBtnClick = stSlot(this, &StMoviePlayerGUI::doAudioStreamsCombo);
96
     myBtnAudio->setDrawShadow(true);
97
@@ -620,10 +623,18 @@
98
 void StMoviePlayerGUI::fillPanoramaMenu(StGLMenu* theMenu) {
99
     theMenu->addItem(tr(MENU_VIEW_SURFACE_PLANE),
100
                      myImage->params.ViewMode, StViewSurface_Plain);
101
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_THEATER),
102
+                     myImage->params.ViewMode, StViewSurface_Theater);
103
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_CYLINDER),
104
+                     myImage->params.ViewMode, StViewSurface_Cylinder);
105
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_HEMISPHERE),
106
+                     myImage->params.ViewMode, StViewSurface_Hemisphere);
107
     theMenu->addItem(tr(MENU_VIEW_SURFACE_SPHERE),
108
                      myImage->params.ViewMode, StViewSurface_Sphere);
109
     theMenu->addItem(tr(MENU_VIEW_SURFACE_CUBEMAP),
110
                      myImage->params.ViewMode, StViewSurface_Cubemap);
111
+    theMenu->addItem(tr(MENU_VIEW_SURFACE_CUBEMAP_EAC),
112
+                     myImage->params.ViewMode, StViewSurface_CubemapEAC);
113
     if(myWindow->hasOrientationSensor()) {
114
         theMenu->addItem(tr(myWindow->isPoorOrientationSensor() ? MENU_VIEW_TRACK_HEAD_POOR : MENU_VIEW_TRACK_HEAD),
115
                          myPlugin->params.ToTrackHead);
116
@@ -648,6 +659,8 @@
117
                    myImage->params.TextureFilter, StGLImageProgram::FILTER_NEAREST);
118
     aMenu->addItem(tr(MENU_VIEW_TEXFILTER_LINEAR),
119
                    myImage->params.TextureFilter, StGLImageProgram::FILTER_LINEAR);
120
+    aMenu->addItem(tr(MENU_VIEW_TEXFILTER_TRILINEAR),
121
+                   myImage->params.TextureFilter, StGLImageProgram::FILTER_TRILINEAR);
122
     aMenu->addItem(tr(MENU_VIEW_TEXFILTER_BLEND),
123
                    myImage->params.TextureFilter, StGLImageProgram::FILTER_BLEND);
124
     return aMenu;
125
@@ -749,11 +762,26 @@
126
 
127
     StDelayControl(StMoviePlayerGUI*               theParent,
128
                    const StHandle<StFloat32Param>& theTrackedValue)
129
-    : StGLMessageBox(theParent, theParent->tr(DIALOG_AUDIO_DELAY_TITLE), "", theParent->scale(400), theParent->scale(260)),
130
+    : StGLMessageBox(theParent),
131
       myRange(NULL) {
132
-        changeRectPx().moveX( myRoot->scale( 64));
133
-        changeRectPx().moveY(-myRoot->scale(128));
134
+        int aWidth  = stMin(theParent->scale(400), myRoot->getRectPx().width());
135
+        int aHeight = stMin(theParent->scale(220), myRoot->getRectPx().height());
136
+        const bool isCompact = myRoot->getRectPx().width()  <= myRoot->scale(450)
137
+                            || myRoot->getRectPx().height() <= myRoot->scale(450);
138
+        if(isCompact) {
139
+            aHeight = stMin(theParent->scale(150), aHeight);
140
+        } else {
141
+            changeRectPx().left() = myRoot->scale(64);
142
+            changeRectPx().top() = -myRoot->scale(128);
143
+        }
144
         setCorner(StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_LEFT));
145
+        changeRectPx().right()  = getRectPx().left() + aWidth;
146
+        changeRectPx().bottom() = getRectPx().top()  + aHeight;
147
+        create(theParent->tr(DIALOG_AUDIO_DELAY_TITLE), "", aWidth, aHeight);
148
+        if(isCompact) {
149
+            myMinSizeY = theParent->scale(150);
150
+        }
151
+
152
         StGLButton* aResetBtn = addButton(theParent->tr(BUTTON_RESET));
153
         addButton(theParent->tr(BUTTON_CLOSE));
154
 
155
@@ -903,7 +931,7 @@
156
     const StGLVec3 THE_WHITE(1.0f, 1.0f, 1.0f);
157
     const StString anAbout = tr(ABOUT_DPLUGIN_NAME) + '\n'
158
                            + tr(ABOUT_VERSION) + " " + StVersionInfo::getSDKVersionString()
159
-                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2007-2017", "kirill@sview.ru", "www.sview.ru")
160
+                           + "\n \n" + tr(ABOUT_DESCRIPTION).format("2007-2020", "kirill@sview.ru", "www.sview.ru")
161
                            + "\n\n<b><i>Used projects</i></b>"
162
                            + "\n \nFFmpeg " + stAV::getVersionInfo() + " (" + stAV::getLicenseInfo() + ")\nhttps://ffmpeg.org/"
163
                            + "\n \nOpenAL Soft (LGPL)\nhttp://kcat.strangesoft.net/openal.html"
164
@@ -1274,6 +1302,8 @@
165
     const IconSize anIconSize = scaleIcon(32, aButtonMargins);
166
     aButtonMargins.extend(scale(12));
167
 
168
+    ///
169
+    ///const int aBotOffset = scale(56);
170
     myPanelBottom = new StGLContainer(this, 0, 0, StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_LEFT), scale(4096), scale(56));
171
 
172
     const StGLCorner aLeftCorner = StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT);
173
@@ -1441,19 +1471,59 @@
174
     myBtnReset3d->changeMargins() = aButtonMargins;
175
 }
176
 
177
-void StMoviePlayerGUI::doOpenFile(const size_t ) {
178
-    StGLOpenFile* aDialog = new StGLOpenFile(this, tr(DIALOG_OPEN_FILE), tr(BUTTON_CLOSE));
179
-    aDialog->setMimeList(myPlugin->myVideo->getMimeListVideo());
180
-#if defined(_WIN32)
181
-    //
182
-#else
183
-    aDialog->addHotItem("/", "Root");
184
-#endif
185
-    aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_SdCard));
186
+void StMoviePlayerGUI::doOpenFile(const size_t theFileType) {
187
+    StString aTitle;
188
+    switch(theFileType) {
189
+        case StMovieOpenDialog::Dialog_Audio: {
190
+            aTitle = tr(DIALOG_OPEN_AUDIO);
191
+            break;
192
+        }
193
+        case StMovieOpenDialog::Dialog_Subtitles: {
194
+            aTitle = tr(DIALOG_OPEN_SUBTITLES);
195
+            break;
196
+        }
197
+        case StMovieOpenDialog::Dialog_SingleMovie:
198
+        case StMovieOpenDialog::Dialog_DoubleMovie:
199
+        default: {
200
+            aTitle = tr(DIALOG_OPEN_FILE);
201
+            break;
202
+        }
203
+    }
204
+
205
+    StGLOpenFile* aDialog = new StGLOpenFile(this, aTitle, tr(BUTTON_CLOSE));
206
+    const StString anSdCardPath = getResourceManager()->getFolder(StResourceManager::FolderId_SdCard);
207
+    if(!anSdCardPath.isEmpty()) {
208
+        StString aFolder, aName;
209
+        StFileNode::getFolderAndFile(anSdCardPath, aFolder, aName);
210
+        aDialog->addHotItem(anSdCardPath, stUtfTools::isInteger(aName) ? (StString("sdcard") + aName) : aName);
211
+    }
212
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Downloads));
213
+    aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Documents));
214
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Videos));
215
     aDialog->addHotItem(getResourceManager()->getFolder(StResourceManager::FolderId_Music));
216
-    aDialog->signals.onFileSelected = stSlot(myPlugin, &StMoviePlayer::doOpen1FileFromGui);
217
+
218
+    switch(theFileType) {
219
+        case StMovieOpenDialog::Dialog_Audio: {
220
+            aDialog->signals.onFileSelected = stSlot(myPlugin, &StMoviePlayer::doOpen1AudioFromGui);
221
+            aDialog->setMimeList(myPlugin->myVideo->getMimeListAudio(), "Audio", false);
222
+            break;
223
+        }
224
+        case StMovieOpenDialog::Dialog_Subtitles: {
225
+            aDialog->signals.onFileSelected = stSlot(myPlugin, &StMoviePlayer::doOpen1SubtitleFromGui);
226
+            aDialog->setMimeList(myPlugin->myVideo->getMimeListSubtitles(), "Subtitles", false);
227
+            break;
228
+        }
229
+        case StMovieOpenDialog::Dialog_SingleMovie:
230
+        case StMovieOpenDialog::Dialog_DoubleMovie:
231
+        default: {
232
+            aDialog->signals.onFileSelected = stSlot(myPlugin, &StMoviePlayer::doOpen1FileFromGui);
233
+            aDialog->setDisplayExtra(myPlugin->params.ToMixImagesVideos->getValue());
234
+            aDialog->setMimeList(myPlugin->myVideo->getMimeListVideo(),  "Videos", false);
235
+            aDialog->setMimeList(myPlugin->myVideo->getMimeListImages(), "Images", true);
236
+            aDialog->addHotCheckbox(myPlugin->params.ToMixImagesVideos, myPlugin->params.ToMixImagesVideos->getName());
237
+            break;
238
+        }
239
+    }
240
 
241
     if(myPlugin->params.lastFolder.isEmpty()) {
242
         StHandle<StFileNode> aCurrFile = myPlugin->myPlayList->getCurrentFile();
243
@@ -1484,12 +1554,18 @@
244
         anItem = aMenu->addItem(tr(BUTTON_DELETE), myPlugin->getAction(StMoviePlayer::Action_DeleteFile));
245
         anItem->setIcon(stCMenuIcon("actionDiscard"));
246
 
247
+        const bool hasVideo = myPlugin->myVideo->hasVideoStream();
248
         const StHandle< StArrayList<StString> >& anAudioStreams = myPlugin->myVideo->params.activeAudio->getList();
249
         if(!anAudioStreams.isNull()
250
         && !anAudioStreams->isEmpty()) {
251
             anItem = aMenu->addItem(tr(MENU_AUDIO));
252
             anItem->setIcon(stCMenuIcon("actionStreamAudio"));
253
             anItem->signals.onItemClick += stSlot(this, &StMoviePlayerGUI::doAudioStreamsCombo);
254
+        } else if(hasVideo) {
255
+            anItem = aMenu->addItem(tr(MENU_AUDIO));
256
+            anItem->setIcon(stCMenuIcon("actionStreamAudio"));
257
+            //anItem->signals.onItemClick += stSlot(myPlugin,  &StMoviePlayer::doAddAudioStream);
258
+            anItem->signals.onItemClick += stSlot(this, &StMoviePlayerGUI::doAudioStreamsCombo);
259
         }
260
 
261
         const StHandle< StArrayList<StString> >& aSubsStreams = myPlugin->myVideo->params.activeSubtitles->getList();
262
@@ -1498,9 +1574,15 @@
263
             anItem = aMenu->addItem(tr(MENU_SUBTITLES));
264
             anItem->setIcon(stCMenuIcon("actionStreamSubtitles"));
265
             anItem->signals.onItemClick += stSlot(this, &StMoviePlayerGUI::doSubtitlesStreamsCombo);
266
+        } else if(myPlugin->myVideo->hasAudioStream()
267
+               || hasVideo) {
268
+            anItem = aMenu->addItem(tr(MENU_SUBTITLES));
269
+            anItem->setIcon(stCMenuIcon("actionStreamSubtitles"));
270
+            //anItem->signals.onItemClick += stSlot(myPlugin,  &StMoviePlayer::doAddSubtitleStream);
271
+            anItem->signals.onItemClick += stSlot(this, &StMoviePlayerGUI::doSubtitlesStreamsCombo);
272
         }
273
 
274
-        if(myPlugin->myVideo->hasVideoStream()) {
275
+        if(hasVideo) {
276
             anItem = aMenu->addItem(tr(MENU_VIEW_DISPLAY_RATIO));
277
             anItem->setIcon(stCMenuIcon("actionDisplayRatio"));
278
             anItem->signals.onItemClick += stSlot(this, &StMoviePlayerGUI::doDisplayRatioCombo);
279
@@ -1588,7 +1670,13 @@
280
     myPlugin->params.ToShowFps->signals.onChanged.connect(this, &StMoviePlayerGUI::doShowFPS);
281
 
282
     myImage = new StGLImageRegion(this, theTextureQueue, false);
283
-    myImage->setDragDelayMs(500.0);
284
+    myImage->changeIconPrev()->setTexturePath(iconTexture(stCString("actionBack"), scaleIcon(64)));
285
+    myImage->changeIconPrev()->setDrawShadow(true);
286
+    myImage->changeIconNext()->setTexturePath(iconTexture(stCString("actionNext"), scaleIcon(64)));
287
+    myImage->changeIconNext()->setDrawShadow(true);
288
+    myImage->signals.onOpenItem = stSlot(myPlugin, &StMoviePlayer::doFileNext);
289
+    myImage->setPlayList(thePlayList);
290
+    //myImage->setDragDelayMs(500.0);
291
     myImage->params.DisplayMode->setName(tr(MENU_VIEW_DISPLAY_MODE));
292
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_STEREO]     = tr(MENU_VIEW_DISPLAY_MODE_STEREO);
293
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_ONLY_LEFT]  = tr(MENU_VIEW_DISPLAY_MODE_LEFT);
294
@@ -1596,14 +1684,16 @@
295
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_PARALLEL]   = tr(MENU_VIEW_DISPLAY_MODE_PARALLEL);
296
     myImage->params.DisplayMode->changeValues()[StGLImageRegion::MODE_CROSSYED]   = tr(MENU_VIEW_DISPLAY_MODE_CROSSYED);
297
     myImage->params.ToHealAnamorphicRatio->setValue(true);
298
+    myImage->params.ViewMode->signals.onChanged += stSlot(myPlugin, &StMoviePlayer::doSwitchViewMode);
299
 
300
     mySubtitles = new StGLSubtitles  (myImage, theSubQueue,
301
                                       myPlugin->params.SubtitlesPlace,
302
-                                      myPlugin->params.SubtitlesTopDY,
303
-                                      myPlugin->params.SubtitlesBottomDY,
304
-                                      myPlugin->params.SubtitlesSize,
305
-                                      myPlugin->params.SubtitlesParallax,
306
-                                      myPlugin->params.SubtitlesParser);
307
+                                      myPlugin->params.SubtitlesSize);
308
+    mySubtitles->params.TopDY    = myPlugin->params.SubtitlesTopDY;
309
+    mySubtitles->params.BottomDY = myPlugin->params.SubtitlesBottomDY;
310
+    mySubtitles->params.Parallax = myPlugin->params.SubtitlesParallax;
311
+    mySubtitles->params.Parser   = myPlugin->params.SubtitlesParser;
312
+    mySubtitles->params.ToApplyStereo = myPlugin->params.SubtitlesApplyStereo;
313
 
314
     if(myPlugin->params.ToShowFps->getValue()) {
315
         myFpsWidget = new StGLFpsLabel(this);
316
@@ -1664,6 +1754,21 @@
317
                                   float theAspect) {
318
     const int aNewSizeX = theViewPort.width();
319
     const int aNewSizeY = theViewPort.height();
320
+    int aGapTopX = 0, aGapTopY = 0, aGapBotX = 0, aGapBotY = 0;
321
+    if(isMobile()) {
322
+        // add gap for hidden system navigation buttons
323
+        static const int THE_NAVIGATION_GAPX = 32;
324
+        static const int THE_NAVIGATION_GAPY = 16;
325
+        if(theAspect < 9.0 / 16.0 && theAspect > 0.0) {
326
+            aGapTopY = aGapBotY = stMax(0, scale(stMin(THE_NAVIGATION_GAPY, int((1.0 / theAspect * 360) - 360 * 2))));
327
+        } else if(theAspect > 9.0 / 16.0) {
328
+            aGapTopX = aGapBotX = stMax(0, scale(stMin(THE_NAVIGATION_GAPX, int((theAspect * 360) - 360 * 2))));
329
+        }
330
+    } else {
331
+        aGapTopY = scale(DISPL_Y_REGION_UPPER);
332
+        aGapTopX = scale(DISPL_X_REGION_UPPER);
333
+        aGapBotX = scale(DISPL_X_REGION_BOTTOM);
334
+    }
335
 
336
     // image should fit entire view
337
     myImage->changeRectPx().top()    = -theMargins.top;
338
@@ -1672,11 +1777,14 @@
339
     myImage->changeRectPx().right()  = -theMargins.left + aNewSizeX;
340
 
341
     if(myPanelUpper != NULL) {
342
-        myPanelUpper->changeRectPx().right()  = stMax(aNewSizeX - theMargins.right - theMargins.left, 2);
343
+        myPanelUpper->changeRectPx().top()   = aGapTopY;
344
+        myPanelUpper->changeRectPx().left()  = aGapTopX;
345
+        myPanelUpper->changeRectPx().right() = aGapTopX + stMax(aNewSizeX - theMargins.right - theMargins.left - 2 * aGapTopX, 2);
346
     }
347
     if(myPanelBottom != NULL) {
348
-        const int aGapX = myPanelBottom->changeRectPx().left();
349
-        myPanelBottom->changeRectPx().right() = aGapX + stMax(aNewSizeX - theMargins.right - theMargins.left - 2 * aGapX, 2);
350
+        myPanelBottom->changeRectPx().top()   = -aGapBotY;
351
+        myPanelBottom->changeRectPx().left()  = aGapBotX;
352
+        myPanelBottom->changeRectPx().right() = aGapBotX + stMax(aNewSizeX - theMargins.right - theMargins.left - 2 * aGapBotX, 2);
353
     }
354
 
355
     stglResizeSeekBar();
356
@@ -1686,7 +1794,7 @@
357
 void StMoviePlayerGUI::stglResizeSeekBar() {
358
     if(mySeekBar != NULL
359
     && myPanelBottom != NULL) {
360
-        const int aPanelSizeY = myPanelBottom->getRectPx().height();
361
+        const int aPanelSizeY = myPanelBottom->getRectPx().top() + myPanelBottom->getRectPx().height();
362
         const int aPanelSizeX = myPanelBottom->getRectPx().width();
363
         const int aSeekSizeY  = mySeekBar->getRectPx().height();
364
         const int aBoxWidth   = myTimeBox->getRectPx().width();
365
@@ -1771,16 +1879,62 @@
366
 
367
 }
368
 
369
-void StMoviePlayerGUI::setVisibility(const StPointD_t& theCursor) {
370
+void StMoviePlayerGUI::doGesture(const StGestureEvent& theEvent) {
371
+    if(myImage == NULL) {
372
+        return;
373
+    }
374
+
375
+    if(theEvent.Type == stEvent_Gesture1Tap) {
376
+        myTapTimer.restart();
377
+    } else if(theEvent.Type == stEvent_Gesture1DoubleTap) {
378
+        myTapTimer.stop();
379
+    }
380
+
381
+    for(StGLWidget *aChildIter(getChildren()->getLast()), *aChildActive(NULL); aChildIter != NULL;) {
382
+        aChildActive = aChildIter;
383
+        aChildIter   = aChildIter->getPrev();
384
+        if(aChildActive->isVisibleAndPointIn(getCursorZo())) {
385
+            if(aChildActive == myImage) {
386
+                myImage->doGesture(theEvent);
387
+            }
388
+            return;
389
+        }
390
+    }
391
+}
392
+
393
+void StMoviePlayerGUI::setVisibility(const StPointD_t& theCursor,
394
+                                     bool theToForceHide,
395
+                                     bool theToForceShow) {
396
     const bool toShowAdjust   = myPlugin->params.ToShowAdjustImage->getValue();
397
     const bool toShowPlayList = myPlugin->params.ToShowPlayList->getValue();
398
     const bool hasMainMenu    = myPlugin->params.ToShowMenu->getValue()
399
                              && myMenuRoot != NULL;
400
     const bool hasUpperPanel  = myPlugin->params.ToShowTopbar->getValue()
401
                              && myPanelUpper != NULL;
402
+    const bool hasBottomPanel = myPlugin->params.ToShowBottom->getValue()
403
+                             && (myPanelBottom != NULL || mySeekBar != NULL);
404
 
405
     const int  aRootSizeY     = getRectPx().height();
406
     const bool hasVideo       = myPlugin->myVideo->hasVideoStream();
407
+    if(!hasVideo && !myTapTimer.isOn()
408
+    && !myPlugin->myPlayList->isEmpty()) {
409
+        myEmptyTimer.restart();
410
+    } else {
411
+        myEmptyTimer.stop();
412
+    }
413
+    if(myEmptyTimer.getElapsedTime() >= 2.5) {
414
+        myVisibilityTimer.restart();
415
+        myEmptyTimer.stop();
416
+    }
417
+    if(myTapTimer.getElapsedTime() >= 0.5) {
418
+        myVisibilityTimer.restart();
419
+        myTapTimer.stop();
420
+    }
421
+    if(theToForceShow) {
422
+        myVisibilityTimer.restart();
423
+    } else if(theToForceHide) {
424
+        myVisibilityTimer.restart(THE_VISIBILITY_IDLE_TIME + 0.001);
425
+    }
426
     const bool isMouseActive  = myWindow->isMouseMoved();
427
     const double aStillTime   = myVisibilityTimer.getElapsedTime();
428
 
429
@@ -1800,15 +1954,15 @@
430
                          && aSrcFormat != StFormat_Mono
431
                          && aSrcFormat != StFormat_AUTO;
432
 
433
-    myIsVisibleGUI = !hasVideo
434
-        || isMouseActive
435
+    myIsVisibleGUI = isMouseActive
436
         || aParams.isNull()
437
-        || aStillTime < 2.0
438
+        || aStillTime < THE_VISIBILITY_IDLE_TIME
439
         || (hasUpperPanel && myPanelUpper->isPointIn(theCursor))
440
-        || (myPanelBottom != NULL && int(aRootSizeY * theCursor.y()) > (aRootSizeY - 2 * myPanelBottom->getRectPx().height())
441
-                                  && theCursor.y() < 1.0)
442
-        || (mySeekBar     != NULL && mySeekBar    ->isPointIn(theCursor))
443
-        || (myPlayList    != NULL && toShowPlayList && myPlayList->isPointIn(theCursor))
444
+        || (hasBottomPanel && myPanelBottom != NULL
445
+         && int(aRootSizeY * theCursor.y()) > (aRootSizeY - 2 * myPanelBottom->getRectPx().height())
446
+         && theCursor.y() < 1.0)
447
+        || (hasBottomPanel && mySeekBar != NULL && mySeekBar->isPointIn(theCursor))
448
+        || (hasBottomPanel && myPlayList != NULL && toShowPlayList && myPlayList->isPointIn(theCursor))
449
         || (hasMainMenu           && myMenuRoot->isActive());
450
     if(!myIsVisibleGUI
451
      && myBtnPlay != NULL
452
@@ -1817,7 +1971,7 @@
453
       || theCursor.y() < 0.0 || theCursor.y() > 1.0)) {
454
         myIsVisibleGUI = true;
455
     }
456
-    const float anOpacity = (float )myVisLerp.perform(myIsVisibleGUI, false);
457
+    const float anOpacity = (float )myVisLerp.perform(myIsVisibleGUI, theToForceHide || theToForceShow);
458
     if(isMouseActive) {
459
         myVisibilityTimer.restart();
460
     }
461
@@ -1829,10 +1983,10 @@
462
         myPanelUpper->setOpacity(hasUpperPanel ? anOpacity : 0.0f, true);
463
     }
464
     if(mySeekBar != NULL) {
465
-        mySeekBar->setOpacity(anOpacity, false);
466
+        mySeekBar->setOpacity(hasBottomPanel ? anOpacity : 0.0f, false);
467
     }
468
     if(myPanelBottom != NULL) {
469
-        myPanelBottom->setOpacity(anOpacity, true);
470
+        myPanelBottom->setOpacity(hasBottomPanel ? anOpacity : 0.0f, true);
471
     }
472
 
473
     if(myAdjustOverlay != NULL
474
@@ -1850,7 +2004,7 @@
475
     }
476
     if(myPlayList != NULL
477
     && toShowPlayList) {
478
-        myPlayList->setOpacity(anOpacity, true);
479
+        myPlayList->setOpacity(hasBottomPanel ? anOpacity : 0.0f, true);
480
     }
481
 
482
     const StPlayList::CurrentPosition aCurrPos = myPlugin->myPlayList->getCurrentPosition();
483
@@ -1894,9 +2048,9 @@
484
     if(!toShowPano
485
     &&  hasVideo
486
     && !aParams.isNull()
487
-    &&  st::probePanorama(aParams->StereoFormat,
488
+    /*&&  st::probePanorama(aParams->StereoFormat,
489
                           aParams->Src1SizeX, aParams->Src1SizeY,
490
-                          aParams->Src2SizeX, aParams->Src2SizeY) != StPanorama_OFF) {
491
+                          aParams->Src2SizeX, aParams->Src2SizeY) != StPanorama_OFF*/) {
492
         toShowPano = true;
493
     }
494
     if(myBtnPanorama != NULL) {
495
@@ -1922,9 +2076,13 @@
496
         } else if(::isPointIn(myBtnPanorama, theCursor)) {
497
             size_t aTrPano = MENU_VIEW_SURFACE_PLANE;
498
             switch(aViewMode) {
499
-                case StViewSurface_Plain:   aTrPano = MENU_VIEW_SURFACE_PLANE;   break;
500
-                case StViewSurface_Sphere:  aTrPano = MENU_VIEW_SURFACE_SPHERE;  break;
501
-                case StViewSurface_Cubemap: aTrPano = MENU_VIEW_SURFACE_CUBEMAP; break;
502
+                case StViewSurface_Plain:      aTrPano = MENU_VIEW_SURFACE_PLANE;   break;
503
+                case StViewSurface_Theater:    aTrPano = MENU_VIEW_SURFACE_THEATER; break;
504
+                case StViewSurface_Sphere:     aTrPano = MENU_VIEW_SURFACE_SPHERE;  break;
505
+                case StViewSurface_Hemisphere: aTrPano = MENU_VIEW_SURFACE_HEMISPHERE;  break;
506
+                case StViewSurface_Cubemap:    aTrPano = MENU_VIEW_SURFACE_CUBEMAP;  break;
507
+                case StViewSurface_CubemapEAC: aTrPano = MENU_VIEW_SURFACE_CUBEMAP_EAC; break;
508
+                case StViewSurface_Cylinder:   aTrPano = MENU_VIEW_SURFACE_CYLINDER; break;
509
             }
510
             myDescr->setText(tr(MENU_VIEW_PANORAMA) + "\n" + tr(aTrPano));
511
         } else if(::isPointIn(myBtnAdjust, theCursor)) {
512
@@ -1987,10 +2145,6 @@
513
             aBuilder.getMenu()->addItem(myPlugin->params.ToForceBFormat);
514
         }
515
     }
516
-    if(myWindow->isMobile()) {
517
-        aBuilder.display();
518
-        return;
519
-    }
520
 
521
     //aBuilder.getMenu()->addSplitter();
522
     StGLMenuItem* aDelayItem = NULL;
523
@@ -2017,8 +2171,65 @@
524
     aBuilder.display();
525
 }
526
 
527
+void StMoviePlayerGUI::doSubtitlesPlacement(const size_t ) {
528
+    StGLMenu* aMenu  = new StGLMenu(this, 0, 0, StGLMenu::MENU_VERTICAL, true);
529
+    aMenu->setCorner(StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_RIGHT));
530
+    aMenu->setContextual(true);
531
+    fillSubtitlesFontSize(aMenu);
532
+    fillSubtitlesPlacement(aMenu);
533
+    aMenu->stglInit();
534
+    setFocus(aMenu);
535
+}
536
+
537
+void StMoviePlayerGUI::fillSubtitlesFontSize(StGLMenu* theMenu) {
538
+    StGLMenuItem* anItem = theMenu->addItem(tr(MENU_SUBTITLES_SIZE));
539
+    anItem->setIcon(stCMenuIcon("actionFontSize"), false);
540
+    anItem->changeMargins().right = scale(100 + 16);
541
+    StGLRangeFieldFloat32* aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesSize,
542
+                                                              -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
543
+    aRange->changeRectPx().bottom() = aRange->getRectPx().top() + theMenu->getItemHeight();
544
+    aRange->setFormat(stCString("%02.0f"));
545
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
546
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aBlack);
547
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aBlack);
548
+}
549
+
550
+void StMoviePlayerGUI::fillSubtitlesPlacement(StGLMenu* theMenu) {
551
+    StGLMenuItem* anItem = theMenu->addItem(tr(MENU_SUBTITLES_TOP), myPlugin->params.SubtitlesPlace, ST_VCORNER_TOP);
552
+    anItem->changeMargins().right  = scale(100 + 16);
553
+    StGLRangeFieldFloat32* aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesTopDY,
554
+                                                              -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
555
+    aRange->changeRectPx().bottom() = aRange->getRectPx().top() + theMenu->getItemHeight();
556
+    aRange->setFormat(stCString("%+03.0f"));
557
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
558
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aGreen);
559
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aRed);
560
+
561
+    anItem = theMenu->addItem(tr(MENU_SUBTITLES_BOTTOM), myPlugin->params.SubtitlesPlace, ST_VCORNER_BOTTOM);
562
+    anItem->changeMargins().right  = scale(100 + 16);
563
+    aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesBottomDY,
564
+                                       -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
565
+    aRange->changeRectPx().bottom() = aRange->getRectPx().top() + theMenu->getItemHeight();
566
+    aRange->setFormat(stCString("%+03.0f"));
567
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
568
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aGreen);
569
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aRed);
570
+
571
+    anItem = theMenu->addItem(tr(MENU_SUBTITLES_PARALLAX));
572
+    anItem->changeMargins().right  = scale(100 + 16);
573
+    aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesParallax,
574
+                                       -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
575
+    aRange->changeRectPx().bottom() = aRange->getRectPx().top() + theMenu->getItemHeight();
576
+    aRange->setFormat(stCString("%+03.0f"));
577
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
578
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aBlack);
579
+    aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aBlack);
580
+}
581
+
582
 void StMoviePlayerGUI::doSubtitlesStreamsCombo(const size_t ) {
583
     const StHandle< StArrayList<StString> >& aStreams = myPlugin->myVideo->params.activeSubtitles->getList();
584
+    const bool hasAudioStream = myPlugin->myVideo->hasAudioStream();
585
+    const bool hasVideoStream = myPlugin->myVideo->hasVideoStream();
586
 
587
     StGLCombobox::ListBuilder aBuilder(this);
588
 
589
@@ -2037,64 +2248,40 @@
590
             aBuilder.getMenu()->addItem(aStreams->getValue(aStreamId), myPlugin->params.SubtitlesStream, int32_t(aStreamId));
591
         }
592
     }
593
-    if(myWindow->isMobile()) {
594
-        aBuilder.display();
595
-        return;
596
-    }
597
 
598
     if(!aStreams.isNull()
599
     && !aStreams->isEmpty()) {
600
         //myMenuSubtitles->addSplitter();
601
-        StGLMenuItem* anItem = aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_SIZE));
602
-        anItem->setIcon(stCMenuIcon("actionFontSize"), false);
603
-        anItem->changeMargins().right = scale(100 + 16);
604
-        StGLRangeFieldFloat32* aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesSize,
605
-                                                                 -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
606
-        aRange->changeRectPx().bottom() = aRange->getRectPx().top() + aBuilder.getMenu()->getItemHeight();
607
-        aRange->setFormat(stCString("%02.0f"));
608
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
609
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aBlack);
610
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aBlack);
611
+        if(!myWindow->isMobile()) {
612
+            fillSubtitlesFontSize(aBuilder.getMenu());
613
+        }
614
 
615
         StGLMenu* aPlaceMenu = new StGLMenu(this, 0, 0, StGLMenu::MENU_VERTICAL);
616
+        fillSubtitlesPlacement(aPlaceMenu);
617
+        aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_PLACEMENT), aPlaceMenu)
618
+                          ->signals.onItemClick.connect(this, &StMoviePlayerGUI::doSubtitlesPlacement);
619
+    }
620
 
621
-        anItem = aPlaceMenu->addItem(tr(MENU_SUBTITLES_TOP), myPlugin->params.SubtitlesPlace, ST_VCORNER_TOP);
622
-        anItem->changeMargins().right  = scale(100 + 16);
623
-        aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesTopDY,
624
-                                          -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
625
-        aRange->changeRectPx().bottom() = aRange->getRectPx().top() + aBuilder.getMenu()->getItemHeight();
626
-        aRange->setFormat(stCString("%+03.0f"));
627
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
628
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aGreen);
629
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aRed);
630
-
631
-        anItem = aPlaceMenu->addItem(tr(MENU_SUBTITLES_BOTTOM), myPlugin->params.SubtitlesPlace, ST_VCORNER_BOTTOM);
632
-        anItem->changeMargins().right  = scale(100 + 16);
633
-        aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesBottomDY,
634
-                                          -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
635
-        aRange->changeRectPx().bottom() = aRange->getRectPx().top() + aBuilder.getMenu()->getItemHeight();
636
-        aRange->setFormat(stCString("%+03.0f"));
637
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
638
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aGreen);
639
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aRed);
640
-
641
-        anItem = aPlaceMenu->addItem(tr(MENU_SUBTITLES_PARALLAX));
642
-        anItem->changeMargins().right  = scale(100 + 16);
643
-        aRange = new StGLRangeFieldFloat32(anItem, myPlugin->params.SubtitlesParallax,
644
-                                          -scale(16), 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_RIGHT));
645
-        aRange->changeRectPx().bottom() = aRange->getRectPx().top() + aBuilder.getMenu()->getItemHeight();
646
-        aRange->setFormat(stCString("%+03.0f"));
647
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Default,  aBlack);
648
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Positive, aBlack);
649
-        aRange->setColor(StGLRangeFieldFloat32::FieldColor_Negative, aBlack);
650
-
651
-        anItem = aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_PLACEMENT), aPlaceMenu);
652
-    }
653
-
654
-    aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_PARSER), aParserMenu)
655
-                      ->setIcon(stCMenuIcon("actionTextFormat"), false);
656
-    if(myPlugin->myVideo->hasAudioStream()
657
-    || myPlugin->myVideo->hasVideoStream()) {
658
+    if(!aStreams.isNull()
659
+    && !aStreams->isEmpty()
660
+    && hasVideoStream) {
661
+        StHandle<StStereoParams> aParams = myImage->getSource();
662
+        StFormat aSrcFormat = (StFormat )myPlugin->params.SrcStereoFormat->getValue();
663
+        if(aSrcFormat == StFormat_AUTO && !aParams.isNull()) {
664
+            aSrcFormat = aParams->StereoFormat;
665
+        }
666
+        if(aSrcFormat == StFormat_SideBySide_LR
667
+        || aSrcFormat == StFormat_SideBySide_RL
668
+        || aSrcFormat == StFormat_TopBottom_LR
669
+        || aSrcFormat == StFormat_TopBottom_RL) {
670
+            aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_STEREO), myPlugin->params.SubtitlesApplyStereo);
671
+        }
672
+    }
673
+    if(!myWindow->isMobile()) {
674
+        aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_PARSER), aParserMenu)
675
+                          ->setIcon(stCMenuIcon("actionTextFormat"), false);
676
+    }
677
+    if(hasAudioStream || hasVideoStream) {
678
         //aBuilder.getMenu()->addSplitter();
679
         aBuilder.getMenu()->addItem(tr(MENU_SUBTITLES_ATTACH))
680
                           ->setIcon(stCMenuIcon("actionOpen"), false)
681
@@ -2259,6 +2446,7 @@
682
     aParams.add(myPlugin->StApplication::params.ActiveDevice);
683
     aParams.add(myImage->params.DisplayMode);
684
     aParams.add(myPlugin->params.ToStickPanorama);
685
+    aParams.add(myPlugin->params.ToSwapJPS);
686
     aRend->getOptions(aParams);
687
     aParams.add(myPlugin->params.ToShowFps);
688
     aParams.add(myPlugin->params.UseGpu);
689
@@ -2271,7 +2459,13 @@
690
     }
691
 
692
     aParams.add(myLangMap->params.language);
693
+    aParams.add(myPlugin->params.ToMixImagesVideos);
694
+    aParams.add(myPlugin->params.SlideShowDelay);
695
     aParams.add(myPlugin->params.IsMobileUI);
696
+#if defined(_WIN32) || defined(__APPLE__) // implemented only on Windows and macOS
697
+    aParams.add(myPlugin->params.IsExclusiveFullScreen);
698
+#endif
699
+    aParams.add(myPlugin->params.ToSmoothUploads);
700
     if(isMobile()) {
701
         //aParams.add(myPlugin->params.ToHideStatusBar);
702
         aParams.add(myPlugin->params.ToHideNavBar);
703
@@ -2284,10 +2478,16 @@
704
         aParams.add(myPlugin->params.BlockSleeping);
705
         aParams.add(myPlugin->params.ToOpenLast);
706
     }
707
-#if !defined(ST_NO_UPDATES_CHECK)
708
+#if defined(ST_UPDATES_CHECK)
709
     aParams.add(myPlugin->params.CheckUpdatesDays);
710
 #endif
711
 
712
+    if(!myWindow->isMobile()) {
713
+        StHandle<StBoolParamNamed> aDefDrawerParam = myPlugin->createDefaultDrawerParam(stCString("StMoviePlayer"),
714
+                                                                                        stCString("sView launcher starts Movie Player"));
715
+        aParams.add(aDefDrawerParam);
716
+    }
717
+
718
     StInfoDialog* aDialog = new StInfoDialog(myPlugin, this, tr(MENU_HELP_SETTINGS), scale(768), scale(300));
719
 
720
     const int aWidthMax  = aDialog->getContent()->getRectPx().width();
721
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayerGUI.h -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayerGUI.h Changed
56
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -115,7 +115,14 @@
9
     ST_LOCAL virtual void stglUpdate(const StPointD_t& thePointZo,
10
                                      bool theIsPreciseInput) ST_ATTR_OVERRIDE;
11
 
12
-    ST_LOCAL void setVisibility(const StPointD_t& theCursor);
13
+    /**
14
+     * Handle gesture.
15
+     */
16
+    ST_LOCAL void doGesture(const StGestureEvent& theEvent);
17
+    ST_LOCAL bool isVisibleGUI() const { return myVisLerp.getValue() > 0.0; }
18
+    ST_LOCAL void setVisibility(const StPointD_t& theCursor,
19
+                                bool theToForceHide = false,
20
+                                bool theToForceShow = false);
21
 
22
         public:
23
 
24
@@ -167,6 +174,8 @@
25
     ST_LOCAL void fillDisplayRatioMenu(StGLMenu* theMenu);
26
     ST_LOCAL void fillSrcFormatMenu(StGLMenu* theMenu);
27
     ST_LOCAL void fillPanoramaMenu (StGLMenu* theMenu);
28
+    ST_LOCAL void fillSubtitlesFontSize(StGLMenu* theMenu);
29
+    ST_LOCAL void fillSubtitlesPlacement(StGLMenu* theMenu);
30
 
31
         private: //! @name mobile interface creation routines
32
 
33
@@ -196,11 +205,12 @@
34
     ST_LOCAL void doChangeHotKey1(const size_t );
35
     ST_LOCAL void doChangeHotKey2(const size_t );
36
 
37
-    ST_LOCAL void doOpenFile(const size_t );
38
+    ST_LOCAL void doOpenFile(const size_t theFileType);
39
     ST_LOCAL void doShowMobileExMenu(const size_t );
40
     ST_LOCAL void doMobileSettings(const size_t );
41
     ST_LOCAL void doAudioStreamsCombo(const size_t );
42
     ST_LOCAL void doSubtitlesStreamsCombo(const size_t );
43
+    ST_LOCAL void doSubtitlesPlacement(const size_t );
44
     ST_LOCAL void doDisplayRatioCombo(const size_t );
45
     ST_LOCAL void doDisplayStereoFormatCombo(const size_t );
46
     ST_LOCAL void doPanoramaCombo(const size_t );
47
@@ -211,6 +221,8 @@
48
     StWindow*           myWindow;           //!< link to the window instance
49
     StTranslations*     myLangMap;          //!< translated strings map
50
     StTimer             myVisibilityTimer;  //!< minimum visible delay
51
+    StTimer             myEmptyTimer;       //!< empty list delay
52
+    StTimer             myTapTimer;         //!< single tap delay
53
     StGLAnimationLerp   myVisLerp;
54
 
55
     StGLImageRegion*    myImage;            //!< the main video frame
56
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayerInfo.h -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayerInfo.h Changed
32
 
1
@@ -140,6 +140,14 @@
2
 #define ST_M4A_MIME_STRING ST_M4A_MIME ":" ST_M4A_EXT ":" ST_M4A_DESC
3
 
4
 /**
5
+ *.insv - Insta360 Video (mp4 unstitched panorama)
6
+ */
7
+#define ST_INSV_MIME "video/x-insv"
8
+#define ST_INSV_DESC "Insta360 Video"
9
+#define ST_INSV_EXT  "insv"
10
+#define ST_INSV_MIME_STRING ST_INSV_MIME ":" ST_INSV_EXT ":" ST_INSV_DESC
11
+
12
+/**
13
  *.mov;*.qt  - QuickTime Video (Apple)
14
  */
15
 #define ST_MOV_MIME "video/quicktime"
16
@@ -328,6 +336,7 @@
17
 ST_M4V_MIME_STRING ";" \
18
 ST_MP4V_MIME_STRING ";" \
19
 ST_M4A_MIME_STRING ";" \
20
+ST_INSV_MIME_STRING ";" \
21
 ST_MOV_MIME_STRING ";" \
22
 ST_QT_MIME_STRING ";" \
23
 ST_FLV_MIME_STRING ";" \
24
@@ -361,6 +370,7 @@
25
 ST_APE_MIME_STRING ";" \
26
 ST_AOB_MIME_STRING ";" \
27
 ST_MP3_MIME_STRING ";" \
28
+ST_M4A_MIME_STRING ";" \
29
 ST_AAC_MIME_STRING ";" \
30
 ST_OGG_MIME_STRING ";" \
31
 ST_OPUS_MIME_STRING ";" \
32
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayerStrings.cpp -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayerStrings.cpp Changed
88
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2013-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -89,6 +89,8 @@
9
                "Top");
10
     theStrings(MENU_SUBTITLES_BOTTOM,
11
                "Bottom");
12
+    theStrings(MENU_SUBTITLES_STEREO,
13
+               "Apply stereo format");
14
     theStrings(MENU_SUBTITLES_PLAIN_TEXT,
15
                "Plain text");
16
     theStrings(MENU_SUBTITLES_LITE_HTML,
17
@@ -185,10 +187,16 @@
18
                "Plane");
19
     theStrings(MENU_VIEW_SURFACE_SPHERE,
20
                "Sphere");
21
+    theStrings(MENU_VIEW_SURFACE_HEMISPHERE,
22
+               "Hemisphere");
23
     theStrings(MENU_VIEW_SURFACE_CYLINDER,
24
                "Cylinder");
25
     theStrings(MENU_VIEW_SURFACE_CUBEMAP,
26
                "Cubemap");
27
+    theStrings(MENU_VIEW_SURFACE_THEATER,
28
+               "Theater");
29
+    theStrings(MENU_VIEW_SURFACE_CUBEMAP_EAC,
30
+               "Equiangular cubemap");
31
     theStrings(MENU_VIEW_TRACK_HEAD,
32
                "Track orientation");
33
     theStrings(MENU_VIEW_TRACK_HEAD_POOR,
34
@@ -217,6 +225,8 @@
35
                "Nearest");
36
     theStrings(MENU_VIEW_TEXFILTER_LINEAR,
37
                "Linear");
38
+    theStrings(MENU_VIEW_TEXFILTER_TRILINEAR,
39
+               "Trilinear");
40
     theStrings(MENU_VIEW_TEXFILTER_BLEND,
41
                "Blend Deinterlace");
42
     theStrings(MENU_CHANGE_DEVICE,
43
@@ -225,6 +235,8 @@
44
                "About Plugin...");
45
     theStrings(MENU_FPS,
46
                "FPS Control");
47
+    theStrings(MENU_EXCLUSIVE_FULLSCREEN,
48
+               "Exclusive Fullscreen mode");
49
     theStrings(MENU_FPS_VSYNC,
50
                "VSync");
51
     theStrings(MENU_FPS_METER,
52
@@ -307,6 +319,8 @@
53
                "Hide system navigation bar");
54
     theStrings(OPTION_OPEN_LAST_ON_STARTUP,
55
                "Open last played file on startup");
56
+    theStrings(OPTION_SWAP_JPS,
57
+               "Swap JPS/PNS views order");
58
 
59
     theStrings(FILE_VIDEO_OPEN,
60
                "Open another movie");
61
@@ -331,6 +345,10 @@
62
                "Choose the video file to open");
63
     theStrings(DIALOG_OPEN_RIGHT,
64
                "Choose RIGHT video file to open");
65
+    theStrings(DIALOG_OPEN_AUDIO,
66
+               "Choose audio file to attach");
67
+    theStrings(DIALOG_OPEN_SUBTITLES,
68
+               "Choose subtitles file to attach");
69
     theStrings(DIALOG_FILE_INFO,
70
                "File Info");
71
     theStrings(DIALOG_FILE_NOINFO,
72
@@ -643,6 +661,15 @@
73
     addAction(theStrings, StMoviePlayer::Action_PanoramaOnOff,
74
               "DoPanoramaOnOff",
75
               "Enable/disable panorama mode");
76
+    addAction(theStrings, StMoviePlayer::Action_ShowGUI,
77
+              "DoShowGUI",
78
+              "Show/hide GUI");
79
+
80
+    theStrings.addAlias("DoOutStereoNormal",       MENU_VIEW_DISPLAY_MODE_STEREO);
81
+    theStrings.addAlias("DoOutStereoLeftView",     MENU_VIEW_DISPLAY_MODE_LEFT);
82
+    theStrings.addAlias("DoOutStereoRightView",    MENU_VIEW_DISPLAY_MODE_RIGHT);
83
+    theStrings.addAlias("DoOutStereoParallelPair", MENU_VIEW_DISPLAY_MODE_PARALLEL);
84
+    theStrings.addAlias("DoOutStereoCrossEyed",    MENU_VIEW_DISPLAY_MODE_CROSSYED);
85
 }
86
 
87
 };
88
sview-17_04.tar.gz/StMoviePlayer/StMoviePlayerStrings.h -> sview-20_08.tar.gz/StMoviePlayer/StMoviePlayerStrings.h Changed
63
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -103,6 +103,7 @@
9
         MENU_VIEW_TEXFILTER_NEAREST = 1260,
10
         MENU_VIEW_TEXFILTER_LINEAR  = 1261,
11
         MENU_VIEW_TEXFILTER_BLEND   = 1262,
12
+        MENU_VIEW_TEXFILTER_TRILINEAR = 1263,
13
 
14
         MENU_VIEW_ADJUST_RESET      = 1270,
15
         MENU_VIEW_ADJUST_BRIGHTNESS = 1271,
16
@@ -113,10 +114,13 @@
17
         MENU_VIEW_SURFACE_SPHERE    = 1281,
18
         MENU_VIEW_SURFACE_CYLINDER  = 1282,
19
         MENU_VIEW_SURFACE_CUBEMAP   = 1283,
20
+        MENU_VIEW_SURFACE_HEMISPHERE= 1284,
21
         MENU_VIEW_TRACK_HEAD        = 1285,
22
         MENU_VIEW_TRACK_HEAD_POOR   = 1286,
23
         MENU_VIEW_TRACK_HEAD_AUDIO  = 1287,
24
         MENU_VIEW_STICK_PANORAMA360 = 1288,
25
+        MENU_VIEW_SURFACE_CUBEMAP_EAC = 1293,
26
+        MENU_VIEW_SURFACE_THEATER   = 1294,
27
 
28
         // Root -> Audio menu
29
         MENU_AUDIO = 1300,
30
@@ -140,6 +144,7 @@
31
         MENU_SUBTITLES_PLACEMENT= 1357,
32
         MENU_SUBTITLES_TOP      = 1358,
33
         MENU_SUBTITLES_BOTTOM   = 1359,
34
+        MENU_SUBTITLES_STEREO   = 1370,
35
 
36
         MENU_SUBTITLES_PLAIN_TEXT = 1360,
37
         MENU_SUBTITLES_LITE_HTML  = 1361,
38
@@ -148,6 +153,7 @@
39
         MENU_CHANGE_DEVICE  = 1400, // Root -> Output -> Change Device menu
40
         MENU_ABOUT_RENDERER = 1401,
41
         MENU_FPS            = 1402,
42
+        MENU_EXCLUSIVE_FULLSCREEN = 1404,
43
 
44
         // Root -> Output -> FPS Control menu
45
         MENU_FPS_VSYNC      = 1420,
46
@@ -194,6 +200,7 @@
47
         OPTION_EXIT_ON_ESCAPE_WINDOWED     = 1705,
48
         OPTION_HIDE_NAVIGATION_BAR         = 1710,
49
         OPTION_OPEN_LAST_ON_STARTUP        = 1711,
50
+        OPTION_SWAP_JPS                    = 1712,
51
 
52
         // Open/Save dialogs
53
         DIALOG_OPEN_FILE       = 2000,
54
@@ -204,6 +211,8 @@
55
         DIALOG_DELETE_FILE_TITLE    = 2005,
56
         DIALOG_DELETE_FILE_QUESTION = 2006,
57
         DIALOG_FILE_DECODERS   = 2007,
58
+        DIALOG_OPEN_AUDIO      = 2008,
59
+        DIALOG_OPEN_SUBTITLES  = 2009,
60
 
61
         DIALOG_SAVE_SNAPSHOT   = 2010,
62
         DIALOG_NOTHING_TO_SAVE = 2011,
63
sview-17_04.tar.gz/StMoviePlayer/StVideo/StAVPacketQueue.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StAVPacketQueue.cpp Changed
97
 
1
@@ -45,6 +45,7 @@
2
   myCodecCtx(NULL),
3
   myCodec(NULL),
4
   myCodecAuto(NULL),
5
+  myCodecAutoId(AV_CODEC_ID_NONE),
6
   myGetFrmtInit(NULL),
7
   myGetBuffInit(NULL),
8
   myPtsStartBase(0.0),
9
@@ -103,14 +104,58 @@
10
     myFormatCtx      = theFormatCtx;
11
     myStream         = myFormatCtx->streams[theStreamId];
12
     myStreamId       = theStreamId;
13
-    myCodecCtx       = myStream->codec;
14
     myPtsStartBase   = detectPtsStartBase(theFormatCtx);
15
     myPtsStartStream = unitsToSeconds(myStream->start_time);
16
+    myIsAttachedPic  = stAV::isAttachedPicture(myStream);
17
+    if(stAV::getCodecType(myStream) != getCodecType()) {
18
+        signals.onError(stCString("Internal error: unsupported codec type"));
19
+        deinit();
20
+        return false;
21
+    }
22
+#ifdef ST_AV_NEWCODECPAR
23
+    myCodecAutoId = myStream->codecpar->codec_id;
24
+    myCodecCtx = avcodec_alloc_context3(NULL);
25
+    if(avcodec_parameters_to_context(myCodecCtx, myStream->codecpar) < 0) {
26
+        signals.onError(stCString("Internal error: unable to copy codec parameters"));
27
+        deinit();
28
+        return false;
29
+    }
30
+
31
+#else
32
+    myCodecCtx    = stAV::getCodecCtx(myStream);
33
+    myCodecAutoId = myCodecCtx->codec_id;
34
+#endif
35
+
36
     myGetFrmtInit    = myCodecCtx->get_format;
37
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
38
     myGetBuffInit    = myCodecCtx->get_buffer2;
39
 #endif
40
-    myIsAttachedPic = stAV::isAttachedPicture(myStream);
41
+
42
+    if(myCodecAutoId == AV_CODEC_ID_TEXT) {
43
+        return true; // special case - decoder is not needed
44
+    }
45
+
46
+    myCodec = NULL;
47
+    myCodecAuto = avcodec_find_decoder(myCodecAutoId);
48
+    if(myCodecAuto == NULL) {
49
+        switch(getCodecType()) {
50
+            case AVMEDIA_TYPE_VIDEO:
51
+                signals.onError(stCString("FFmpeg: Video codec not found"));
52
+                break;
53
+            case AVMEDIA_TYPE_AUDIO:
54
+                signals.onError(stCString("FFmpeg: Audio codec not found"));
55
+                break;
56
+            case AVMEDIA_TYPE_SUBTITLE:
57
+                signals.onError(stCString("FFmpeg: Subtitle codec not found"));
58
+                break;
59
+            default:
60
+                signals.onError(stCString("FFmpeg: codec not found"));
61
+                break;
62
+        }
63
+        deinit();
64
+        return false;
65
+    }
66
+
67
     return true;
68
 }
69
 
70
@@ -118,16 +163,25 @@
71
     myFileName.clear();
72
     myFormatCtx = NULL;
73
     myStream    = NULL;
74
+    if(myCodec != NULL) {
75
+        fillCodecInfo(NULL);
76
+    }
77
+#ifdef ST_AV_NEWCODECPAR
78
+    if(myCodecCtx != NULL) {
79
+        avcodec_free_context(&myCodecCtx);
80
+    }
81
+#else
82
     if(myCodec != NULL && myCodecCtx != NULL) {
83
         avcodec_close(myCodecCtx);
84
         myCodecCtx->get_format  = myGetFrmtInit;
85
     #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
86
         myCodecCtx->get_buffer2 = myGetBuffInit;
87
     #endif
88
-        fillCodecInfo(NULL);
89
     }
90
+#endif
91
     myCodec       = NULL;
92
     myCodecAuto   = NULL;
93
+    myCodecAutoId = AV_CODEC_ID_NONE;
94
     myCodecCtx    = NULL;
95
     myGetFrmtInit = NULL;
96
     myGetBuffInit = NULL;
97
sview-17_04.tar.gz/StMoviePlayer/StVideo/StAVPacketQueue.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StAVPacketQueue.h Changed
43
 
1
@@ -59,6 +59,11 @@
2
     ST_LOCAL void clear();
3
 
4
     /**
5
+     * Return codec type.
6
+     */
7
+    ST_LOCAL virtual AVMediaType getCodecType() const = 0;
8
+
9
+    /**
10
      * Close stream.
11
      */
12
     ST_LOCAL virtual void deinit();
13
@@ -229,9 +234,9 @@
14
     /**
15
      * Open stream.
16
      */
17
-    ST_LOCAL virtual bool init(AVFormatContext*   theFormatCtx,
18
-                               const unsigned int theStreamId,
19
-                               const StString&    theFileName);
20
+    ST_LOCAL bool init(AVFormatContext*   theFormatCtx,
21
+                       const unsigned int theStreamId,
22
+                       const StString&    theFileName);
23
 
24
         protected: //! @name Fields should be full-controlled by heirs
25
 
26
@@ -241,6 +246,7 @@
27
     AVCodecContext*  myCodecCtx;       //!< codec context
28
     AVCodec*         myCodec;          //!< codec
29
     AVCodec*         myCodecAuto;      //!< original codec (autodetected - before overriding)
30
+    AVCodecID        myCodecAutoId;    //!< original code id
31
     typedef AVPixelFormat (*aGetFrmt_t)(AVCodecContext* , const AVPixelFormat* );
32
     typedef int           (*aGetBuf2_t)(AVCodecContext* , AVFrame* frame, int );
33
     aGetFrmt_t       myGetFrmtInit;
34
@@ -270,6 +276,8 @@
35
     double           mySizeSeconds;    //!< cumulative packets length in seconds
36
     mutable StMutex  myMutex;          //!< lock for thread-safety
37
 
38
+        protected:
39
+
40
     StString         myCodecName;      //!< active codec name
41
     StString         myCodecDesc;      //!< active codec description
42
     StString         myCodecStr;       //!< active codec description
43
sview-17_04.tar.gz/StMoviePlayer/StVideo/StAudioQueue.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StAudioQueue.cpp Changed
102
 
1
@@ -736,29 +736,22 @@
2
         return false;
3
     }
4
 
5
-    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)
6
-    || myCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO) {
7
+    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)) {
8
         signals.onError(stCString("FFmpeg: invalid stream"));
9
         deinit();
10
         return false;
11
     }
12
 
13
-    // get AUDIO codec
14
-    myCodec = avcodec_find_decoder(myCodecCtx->codec_id);
15
-    if(myCodec == NULL) {
16
-        signals.onError(stCString("FFmpeg: audio codec not found"));
17
-        deinit();
18
-        return false;
19
-    }
20
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
21
-    if(avcodec_open2(myCodecCtx, myCodec, NULL) < 0) {
22
+    if(avcodec_open2(myCodecCtx, myCodecAuto, NULL) < 0) {
23
 #else
24
-    if(avcodec_open(myCodecCtx, myCodec) < 0) {
25
+    if(avcodec_open(myCodecCtx, myCodecAuto) < 0) {
26
 #endif
27
         signals.onError(stCString("FFmpeg: could not open audio codec"));
28
         deinit();
29
         return false;
30
     }
31
+    myCodec = myCodecAuto;
32
 
33
     // setup buffers
34
     if(!initBuffers()) {
35
@@ -923,6 +916,8 @@
36
         );
37
     }
38
     myDbgPrevQueued = aQueued;
39
+#else
40
+    (void )myDbgPrevQueued;
41
 #endif
42
 
43
     if((aState == AL_PLAYING
44
@@ -1112,18 +1107,38 @@
45
     int anAudioPktSize = thePacket->getSize();
46
     bool checkMoreFrames = false;
47
     int isGotFrame = 0;
48
+    bool toSendPacket = true;
49
     // packet could store multiple frames
50
     for(;;) {
51
         while(anAudioPktSize > 0) {
52
             int aDataSize = (int )myBufferSrc.getBufferSizeWhole();
53
 
54
-        #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
55
+        #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
56
+            (void )aDataSize;
57
+            if(toSendPacket) {
58
+                const int aRes = avcodec_send_packet(myCodecCtx, thePacket->getType() == StAVPacket::DATA_PACKET ? thePacket->getAVpkt() : NULL);
59
+                if(aRes < 0 && aRes != AVERROR_EOF) {
60
+                    anAudioPktSize = 0;
61
+                    break;
62
+                }
63
+                toSendPacket = false;
64
+            }
65
+
66
+            myFrame.reset();
67
+            const int aRes2 = avcodec_receive_frame(myCodecCtx, myFrame.Frame);
68
+            if(aRes2 < 0) {
69
+                anAudioPktSize = 0;
70
+                break;
71
+            }
72
+            isGotFrame = 1;
73
+            int aLen1 = 0; // dummy for code compatible with old syntax
74
+        #elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
75
             StAVPacket anAvPkt;
76
             anAvPkt.getAVpkt()->data = (uint8_t* )anAudioPktData;
77
             anAvPkt.getAVpkt()->size = anAudioPktSize;
78
+            (void )toSendPacket;
79
 
80
             #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 40, 0))
81
-            //av_frame_unref(myFrame.Frame);
82
             (void )aDataSize;
83
             myFrame.reset();
84
             const int aLen1 = avcodec_decode_audio4(myCodecCtx, myFrame.Frame,
85
@@ -1270,6 +1285,16 @@
86
                 aPts = 0.0;
87
                 continue;
88
             }
89
+            case StAVPacket::DATA_PACKET: {
90
+                break;
91
+            }
92
+            case StAVPacket::LAST_PACKET: {
93
+            #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
94
+                break; // redirect NULL packet to avcodec_send_packet()
95
+            #else
96
+                continue;
97
+            #endif
98
+            }
99
             case StAVPacket::END_PACKET: {
100
                 pushPlayEvent(ST_PLAYEVENT_NONE);
101
                 // TODO (Kirill Gavrilov#3#) improve file-by-file playback
102
sview-17_04.tar.gz/StMoviePlayer/StVideo/StAudioQueue.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StAudioQueue.h Changed
24
 
1
@@ -63,14 +63,19 @@
2
     }
3
 
4
     /**
5
+     * Return codec type.
6
+     */
7
+    ST_LOCAL virtual AVMediaType getCodecType() const ST_ATTR_OVERRIDE { return AVMEDIA_TYPE_AUDIO; }
8
+
9
+    /**
10
      * Initialization function.
11
      * @param theFormatCtx pointer to video format context
12
      * @param theStreamId  stream id in video format context
13
      * @return true if no error
14
      */
15
-    ST_LOCAL virtual bool init(AVFormatContext*   theFormatCtx,
16
-                               const unsigned int theStreamId,
17
-                               const StString&    theFileName) ST_ATTR_OVERRIDE;
18
+    ST_LOCAL bool init(AVFormatContext*   theFormatCtx,
19
+                       const unsigned int theStreamId,
20
+                       const StString&    theFileName);
21
 
22
     /**
23
      * Clean function.
24
sview-17_04.tar.gz/StMoviePlayer/StVideo/StSubtitleQueue.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StSubtitleQueue.cpp Changed
124
 
1
@@ -42,6 +42,7 @@
2
   myOutQueue(theSubtitlesQueue),
3
   myThread(NULL),
4
   evDowntime(true),
5
+  myImageScale(1.0f),
6
   toQuit(false) {
7
     myThread = new StThread(threadFunction, (void* )this, "StSubtitleQueue");
8
 }
9
@@ -59,36 +60,25 @@
10
 bool StSubtitleQueue::init(AVFormatContext*   theFormatCtx,
11
                            const unsigned int theStreamId,
12
                            const StString&    theFileName) {
13
-    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)
14
-    || myCodecCtx->codec_type != AVMEDIA_TYPE_SUBTITLE) {
15
+    myImageScale = 1.0f;
16
+    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)) {
17
         signals.onError(stCString("FFmpeg: invalid stream"));
18
         deinit();
19
         return false;
20
     }
21
 
22
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 51, 100))
23
-    if(myCodecCtx->codec_id != AV_CODEC_ID_TEXT) {
24
-#else
25
-    if(myCodecCtx->codec_id != CODEC_ID_TEXT) {
26
-#endif
27
-        // find the decoder for the subtitles stream
28
-        myCodec = avcodec_find_decoder(myCodecCtx->codec_id);
29
-        if(myCodec == NULL) {
30
-            signals.onError(stCString("FFmpeg: Subtitle decoder not found"));
31
-            deinit();
32
-            return false;
33
-        }
34
-
35
+    if(myCodecAutoId != AV_CODEC_ID_TEXT) {
36
         // open SUBTITLE codec
37
     #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
38
-        if(avcodec_open2(myCodecCtx, myCodec, NULL) < 0) {
39
+        if(avcodec_open2(myCodecCtx, myCodecAuto, NULL) < 0) {
40
     #else
41
-        if(avcodec_open(myCodecCtx, myCodec) < 0) {
42
+        if(avcodec_open(myCodecCtx, myCodecAuto) < 0) {
43
     #endif
44
             signals.onError(stCString("FFmpeg: Could not open subtitle codec"));
45
             deinit();
46
             return false;
47
         }
48
+        myCodec = myCodecAuto;
49
 
50
         // initialize ASS parser
51
     #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 95, 0))
52
@@ -97,6 +87,9 @@
53
                    myCodecCtx->subtitle_header_size);
54
     #endif
55
     }
56
+    if(myCodecAuto != NULL && StString(myCodecAuto->name).isEquals(stCString("pgssub"))) {
57
+        myImageScale = 0.5f;
58
+    }
59
     fillCodecInfo(myCodec);
60
     return true;
61
 }
62
@@ -137,6 +130,12 @@
63
                 myOutQueue->clear();
64
                 continue;
65
             }
66
+            case StAVPacket::DATA_PACKET: {
67
+                break;
68
+            }
69
+            case StAVPacket::LAST_PACKET: {
70
+                continue; // ignore as avcodec_send_packet() is not used
71
+            }
72
             case StAVPacket::END_PACKET: {
73
                 if(toQuit) {
74
                     return;
75
@@ -177,6 +176,15 @@
76
 
77
                             StHandle<StSubItem> aNewSubItem = new StSubItem(aPts, aPts + aDuration);
78
                             aNewSubItem->Image.initTrash(StImagePlane::ImgRGBA, aRect->w, aRect->h);
79
+                            aNewSubItem->Scale = myImageScale;
80
+
81
+                        #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 9, 100))
82
+                            uint8_t** anImgData = aRect->data;
83
+                            int* anImgLineSizes = aRect->linesize;
84
+                        #else
85
+                            uint8_t** anImgData = aRect->pict.data;
86
+                            int* anImgLineSizes = aRect->pict.linesize;
87
+                        #endif
88
 
89
                             SwsContext* aCtxToRgb = sws_getContext(aRect->w, aRect->h, stAV::PIX_FMT::PAL8,
90
                                                                    aRect->w, aRect->h, stAV::PIX_FMT::RGBA32,
91
@@ -186,20 +194,14 @@
92
                             }
93
 
94
                             uint8_t* aDstData[4] = {
95
-                                (uint8_t* )aNewSubItem->Image.getData(),
96
-                                NULL,
97
-                                NULL,
98
-                                NULL
99
+                                (uint8_t* )aNewSubItem->Image.getData(), NULL, NULL, NULL
100
                             };
101
                             /*const*/ int aDstLinesize[4] = {
102
-                                (int )aNewSubItem->Image.getSizeRowBytes(),
103
-                                0,
104
-                                0,
105
-                                0
106
+                                (int )aNewSubItem->Image.getSizeRowBytes(), 0, 0, 0
107
                             };
108
 
109
                             sws_scale(aCtxToRgb,
110
-                                      aRect->pict.data, aRect->pict.linesize,
111
+                                      anImgData, anImgLineSizes,
112
                                       0, aRect->h,
113
                                       aDstData, aDstLinesize);
114
                             sws_freeContext(aCtxToRgb);
115
@@ -220,7 +222,7 @@
116
                         }
117
                         case SUBTITLE_ASS: {
118
                             StString aTextData = aRect->ass;
119
-                            StHandle<StSubItem> aNewSubItem = myASS.parseEvent(aTextData, aPts);
120
+                            StHandle<StSubItem> aNewSubItem = myASS.parseEvent(aTextData, aPts, aDuration);
121
                             if(!aNewSubItem.isNull()) {
122
                                 myOutQueue->push(aNewSubItem);
123
                             }
124
sview-17_04.tar.gz/StMoviePlayer/StVideo/StSubtitleQueue.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StSubtitleQueue.h Changed
32
 
1
@@ -51,14 +51,19 @@
2
     }
3
 
4
     /**
5
+     * Return codec type.
6
+     */
7
+    ST_LOCAL virtual AVMediaType getCodecType() const ST_ATTR_OVERRIDE { return AVMEDIA_TYPE_SUBTITLE; }
8
+
9
+    /**
10
      * Initialization function.
11
      * @param theFormatCtx pointer to video format context
12
      * @param streamId     stream id in video format context
13
      * @return true if no error
14
      */
15
-    ST_LOCAL virtual bool init(AVFormatContext*   theFormatCtx,
16
-                               const unsigned int theStreamId,
17
-                               const StString&    theFileName) ST_ATTR_OVERRIDE;
18
+    ST_LOCAL bool init(AVFormatContext*   theFormatCtx,
19
+                       const unsigned int theStreamId,
20
+                       const StString&    theFileName);
21
 
22
     /**
23
      * Clean function.
24
@@ -76,6 +81,7 @@
25
     StThread*            myThread;   //!< decoding loop thread
26
     StSubtitlesASS       myASS;      //!< ASS subtitles parser
27
     StCondition          evDowntime;
28
+    float                myImageScale;
29
     volatile bool        toQuit;
30
 
31
 };
32
sview-17_04.tar.gz/StMoviePlayer/StVideo/StSubtitlesASS.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StSubtitlesASS.cpp Changed
83
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -191,18 +191,39 @@
9
             if(*anIter.getBufferHere() == stUtf8_t('i')) {
10
                 // italic
11
                 if(       *anIter.getBufferNext() == stUtf8_t('1')) {
12
-                    ///aText += "<i>";  // on
13
+                    aText += "<i>";
14
                 } else if(*anIter.getBufferNext() == stUtf8_t('0')) {
15
-                    ///aText += "</i>"; // off
16
+                    aText += "</i>";
17
                 }
18
             } else if(*anIter.getBufferHere() == stUtf8_t('b')) {
19
                 // bold
20
                 if(       *anIter.getBufferNext() == stUtf8_t('1')) {
21
-                    ///aText += "<b>";  // on
22
+                    aText += "<b>";
23
                 } else if(*anIter.getBufferNext() == stUtf8_t('0')) {
24
-                    ///aText += "</b>"; // off
25
+                    aText += "</b>";
26
                 }
27
-            }// else
28
+            } else if(*anIter.getBufferHere() == stUtf8_t('u')) {
29
+                // underline
30
+                if(       *anIter.getBufferNext() == stUtf8_t('1')) {
31
+                    //aText += "<u>";
32
+                } else if(*anIter.getBufferNext() == stUtf8_t('0')) {
33
+                    //aText += "</u>";
34
+                }
35
+            } else if(*anIter.getBufferHere() == stUtf8_t('s')) {
36
+                // strikeout
37
+                if(       *anIter.getBufferNext() == stUtf8_t('1')) {
38
+                    //aText += "<s>";
39
+                } else if(*anIter.getBufferNext() == stUtf8_t('0')) {
40
+                    //aText += "</s>";
41
+                }
42
+            } else if(*anIter.getBufferHere() == stUtf8_t('f')) {
43
+                if(*anIter.getBufferNext() == stUtf8_t('s')) {
44
+                    // font size
45
+                } else if(*anIter.getBufferNext() == stUtf8_t('n')) {
46
+                    // font name
47
+                }
48
+            }
49
+            // else
50
 
51
             // search for trailing bracket
52
             while(*anIter != stUtf32_t('}') && *anIter != 0) {
53
@@ -216,6 +237,9 @@
54
             aStart = anIter.getIndex() + 1;
55
         }
56
     }
57
+    if(aStart != 0) {
58
+        aText += theText.subString(aStart, theText.Length);
59
+    }
60
     if(!aText.isEmpty()) {
61
         // replace only if text contains style codes
62
         theText = aText;
63
@@ -223,7 +247,8 @@
64
 }
65
 
66
 StHandle<StSubItem> StSubtitlesASS::parseEvent(const StString& theString,
67
-                                               const double    thePts) {
68
+                                               double thePts,
69
+                                               double theDuration) {
70
     if(!isValid() || !theString.isStartsWithIgnoreCase(HEADER_Dialog)) {
71
         return StHandle<StSubItem>();
72
     }
73
@@ -249,6 +274,9 @@
74
     parseStyle(aText);
75
 
76
     double aDuration = parseTime(aList->getValue(myIdPtsEnd)) - parseTime(aList->getValue(myIdPtsStart));
77
+    if(aDuration <= 0.0) {
78
+        aDuration = theDuration; // why ASS information is wrong here on current FFmpeg?
79
+    }
80
     aText.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT);
81
     aText.replaceFast(ST_ASS_NEWLINE,    ST_NEWLINE_REPLACEMENT);
82
     aText.replaceFast(ST_ASS_NEWLINE2,   ST_NEWLINE_REPLACEMENT);
83
sview-17_04.tar.gz/StMoviePlayer/StVideo/StSubtitlesASS.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StSubtitlesASS.h Changed
18
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -63,7 +63,8 @@
9
      * Parse the dialog event and returns a subtitle item.
10
      */
11
     ST_LOCAL StHandle<StSubItem> parseEvent(const StString& theString,
12
-                                            const double    thePts);
13
+                                            double thePts,
14
+                                            double theDuration);
15
 
16
         private:
17
 
18
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideo.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideo.cpp Changed
563
 
1
@@ -20,7 +20,10 @@
2
 #include "../StMoviePlayerInfo.h"
3
 #include "../StMoviePlayerStrings.h"
4
 
5
+#include "../StImageViewer/StImagePluginInfo.h"
6
+
7
 #include <StStrings/StFormatTime.h>
8
+#include <StAV/StAVIOJniHttpContext.h>
9
 
10
 using namespace StMoviePlayerStrings;
11
 
12
@@ -33,8 +36,69 @@
13
         aStVideo->mainLoop();
14
         return SV_THREAD_RETURN 0;
15
     }
16
+
17
+#ifdef ST_AV_NEWCODECPAR
18
+    /**
19
+     * Format framerate value.
20
+     */
21
+    static StString formatFps(double theVal) {
22
+        //const uint64_t aVal = lrintf(theVal * 100.0);
23
+        const uint64_t aVal = uint64_t(theVal * 100.0 + 0.5);
24
+        char aBuff[256];
25
+        if(aVal == 0) {
26
+            stsprintf(aBuff, sizeof(aBuff), "%1.4f", theVal);
27
+        } else if(aVal % 100) {
28
+            stsprintf(aBuff, sizeof(aBuff), "%3.2f", theVal);
29
+        } else if(aVal % (100 * 1000)) {
30
+            stsprintf(aBuff, sizeof(aBuff), "%1.0f", theVal);
31
+        } else {
32
+            stsprintf(aBuff, sizeof(aBuff), "%1.0fk", theVal / 1000);
33
+        }
34
+        return aBuff;
35
+    }
36
+#endif
37
+
38
+    /**
39
+     * Format stream info.
40
+     */
41
+    static StString formatStreamInfo(const AVStream* theStream) {
42
+        AVCodecContext* aCodecCtx = stAV::getCodecCtx(theStream);
43
+        char aFrmtBuff[4096] = {};
44
+        avcodec_string(aFrmtBuff, sizeof(aFrmtBuff), aCodecCtx, 0);
45
+        StString aStreamInfo(aFrmtBuff);
46
+
47
+    #ifdef ST_AV_NEWCODECPAR
48
+        //aStreamInfo = aStreamInfo + ", " + theStream->codec_info_nb_frames + ", " + theStream->time_base.num + "/" + theStream->time_base.den;
49
+        if(theStream->sample_aspect_ratio.num && av_cmp_q(theStream->sample_aspect_ratio, theStream->codecpar->sample_aspect_ratio)) {
50
+            AVRational aDispAspectRatio;
51
+            av_reduce(&aDispAspectRatio.num, &aDispAspectRatio.den,
52
+                      theStream->codecpar->width  * int64_t(theStream->sample_aspect_ratio.num),
53
+                      theStream->codecpar->height * int64_t(theStream->sample_aspect_ratio.den),
54
+                      1024 * 1024);
55
+            aStreamInfo = aStreamInfo + ", SAR " + theStream->sample_aspect_ratio.num + ":" + theStream->sample_aspect_ratio.den
56
+                                       + " DAR " + aDispAspectRatio.num + ":" + aDispAspectRatio.den;
57
+        }
58
+
59
+        if(theStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
60
+            if(theStream->avg_frame_rate.den != 0 && theStream->avg_frame_rate.num != 0) {
61
+                aStreamInfo += StString(", ") + formatFps(av_q2d(theStream->avg_frame_rate)) + " fps";
62
+            }
63
+            if(theStream->r_frame_rate.den != 0 && theStream->r_frame_rate.num != 0) {
64
+                aStreamInfo += StString(", ") + formatFps(av_q2d(theStream->r_frame_rate)) + " tbr";
65
+            }
66
+            if(theStream->time_base.den != 0 && theStream->time_base.num != 0) {
67
+                aStreamInfo += StString(", ") + formatFps(1 / av_q2d(theStream->time_base)) + " tbn";
68
+            }
69
+            if(aCodecCtx->time_base.den != 0 && aCodecCtx->time_base.num != 0) {
70
+                aStreamInfo += StString(", ") + formatFps(1 / av_q2d(aCodecCtx->time_base)) + " tbc";
71
+            }
72
+        }
73
+    #endif
74
+        return aStreamInfo;
75
+    }
76
 }
77
 
78
+const char* StVideo::ST_IMAGES_MIME_STRING = ST_IMAGE_PLUGIN_MIME_CHAR;
79
 const char* StVideo::ST_VIDEOS_MIME_STRING = ST_VIDEO_PLUGIN_MIME_CHAR;
80
 
81
 StVideo::StVideo(const std::string&                 theALDeviceName,
82
@@ -47,6 +111,7 @@
83
 : myMimesVideo(ST_VIDEOS_MIME_STRING),
84
   myMimesAudio(ST_AUDIOS_MIME_STRING),
85
   myMimesSubs(ST_SUBTIT_MIME_STRING),
86
+  myMimesImages(ST_IMAGES_MIME_STRING),
87
   myResMgr(theResMgr),
88
   myLangMap(theLangMap),
89
   mySlaveCtx(NULL),
90
@@ -252,7 +317,6 @@
91
     // open video file
92
     StString aFileName, aDummy;
93
     StFileNode::getFolderAndFile(theFileToLoad, aDummy, aFileName);
94
-    AVFormatContext* aFormatCtx = NULL;
95
 
96
     StHandle<StAVIOContext> anIOContext;
97
     if(StFileNode::isContentProtocolPath(theFileToLoad)) {
98
@@ -260,12 +324,26 @@
99
         if(aFileDescriptor != -1) {
100
             StHandle<StAVIOFileContext> aFileCtx = new StAVIOFileContext();
101
             if(aFileCtx->openFromDescriptor(aFileDescriptor, "rb")) {
102
-                aFormatCtx = avformat_alloc_context();
103
-                aFormatCtx->pb = aFileCtx->getAvioContext();
104
                 anIOContext = aFileCtx;
105
             }
106
         }
107
     }
108
+#if defined(__ANDROID__)
109
+    else if(theFileToLoad.isStartsWith(stCString("https://"))) {
110
+        static const bool hasHttpsProtocol = stAV::isEnabledInputProtocol("https");
111
+        if(!hasHttpsProtocol) {
112
+            StHandle<StAVIOJniHttpContext> aHttpCtx = new StAVIOJniHttpContext();
113
+            if(aHttpCtx->open(theFileToLoad)) {
114
+                anIOContext = aHttpCtx;
115
+            }
116
+        }
117
+    }
118
+#endif
119
+    AVFormatContext* aFormatCtx = NULL;
120
+    if(!anIOContext.isNull()) {
121
+        aFormatCtx = avformat_alloc_context();
122
+        aFormatCtx->pb = anIOContext->getAvioContext();
123
+    }
124
 
125
 #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0))
126
     int avErrCode = avformat_open_input(&aFormatCtx, theFileToLoad.toCString(), NULL, NULL);
127
@@ -333,10 +411,16 @@
128
 
129
     theInfo.Duration = stMax(theInfo.Duration, stAV::unitsToSeconds(aFormatCtx->duration));
130
     for(unsigned int aStreamId = 0; aStreamId < aFormatCtx->nb_streams; ++aStreamId) {
131
-        AVStream* aStream = aFormatCtx->streams[aStreamId];
132
+        AVStream*         aStream    = aFormatCtx->streams[aStreamId];
133
+        const AVMediaType aCodecType = stAV::getCodecType(aStream);
134
         theInfo.Duration = stMax(theInfo.Duration, stAV::unitsToSeconds(aStream, aStream->duration));
135
 
136
-        if(aStream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
137
+        StString aLang = stAV::meta::readLang(aStream);
138
+        if(aLang == "und") {
139
+            aLang.clear();
140
+        }
141
+
142
+        if(aCodecType == AVMEDIA_TYPE_VIDEO) {
143
             // video track
144
             if(!myVideoMaster->isInitialized()) {
145
                 myVideoMaster->init(aFormatCtx, aStreamId, aTitleString, theNewParams);
146
@@ -367,7 +451,7 @@
147
                 }
148
             } else if(!myVideoSlave->isInitialized()
149
                    && !stAV::isAttachedPicture(aStream)) {
150
-                myVideoSlave->init(aFormatCtx, aStreamId, "", theNewParams);
151
+                myVideoSlave->init(aFormatCtx, aStreamId, aTitleString, theNewParams);
152
                 if(myVideoSlave->isInitialized()) {
153
                     mySlaveCtx    = aFormatCtx;
154
                     mySlaveStream = aStreamId;
155
@@ -394,29 +478,19 @@
156
                     }
157
                 }
158
             }
159
-        } else if(aStream->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
160
+        } else if(aCodecType == AVMEDIA_TYPE_AUDIO) {
161
             // audio track
162
-            AVCodecContext* aCodecCtx = aStream->codec;
163
             StString aCodecName;
164
-            AVCodec* aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
165
+            AVCodec* aCodec = avcodec_find_decoder(stAV::getCodecId(aStream));
166
             if(aCodec != NULL) {
167
                 aCodecName = aCodec->name;
168
             }
169
 
170
+            AVCodecContext* aCodecCtx = stAV::getCodecCtx (aStream);
171
             StString aSampleFormat  = stAV::audio::getSampleFormatString (aCodecCtx);
172
             StString aSampleRate    = stAV::audio::getSampleRateString   (aCodecCtx);
173
             StString aChannelLayout = stAV::audio::getChannelLayoutString(aCodecCtx);
174
 
175
-            StString aLang;
176
-        #if(LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 5, 0))
177
-            stAV::meta::readTag(aStream, stCString("language"), aLang);
178
-        #else
179
-            aLang = aStream->language;
180
-        #endif
181
-            if(aLang == "und") {
182
-                aLang.clear();
183
-            }
184
-
185
             StString aStreamTitle = aCodecName;
186
             if(!aSampleRate.isEmpty()) {
187
                 aStreamTitle += StString(", ") + aSampleRate;
188
@@ -439,28 +513,17 @@
189
 
190
             if(!myAudio->isInitialized()
191
             && (aPrefLangAudio.isEmpty() || aLang == aPrefLangAudio)
192
-            &&  myAudio->init(aFormatCtx, aStreamId, "")) {
193
+            &&  myAudio->init(aFormatCtx, aStreamId, aTitleString)) {
194
                 theInfo.LoadedAudio = (int32_t )(theInfo.AudioList->size() - 1);
195
             }
196
-        } else if(aStream->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
197
+        } else if(aCodecType == AVMEDIA_TYPE_SUBTITLE) {
198
             // subtitles track
199
-            AVCodecContext* aCodecCtx = aStream->codec;
200
             StString aCodecName("PLAIN");
201
-            AVCodec* aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
202
+            AVCodec* aCodec = avcodec_find_decoder(stAV::getCodecId(aStream));
203
             if(aCodec != NULL) {
204
                 aCodecName = aCodec->name;
205
             }
206
 
207
-            StString aLang;
208
-        #if(LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 5, 0))
209
-            stAV::meta::readTag(aStream, stCString("language"), aLang);
210
-        #else
211
-            aLang = aStream->language;
212
-        #endif
213
-            if(aLang == "und") {
214
-                aLang.clear();
215
-            }
216
-
217
             StString aStreamTitle = aCodecName;
218
             if(!aLang.isEmpty()) {
219
                 aStreamTitle += StString(" (") + aLang + ")";
220
@@ -478,7 +541,7 @@
221
     && !theInfo.AudioList->isEmpty()) {
222
         for(unsigned int aStreamId = 0; aStreamId < aFormatCtx->nb_streams; ++aStreamId) {
223
             AVStream* aStream = aFormatCtx->streams[aStreamId];
224
-            if(aStream->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
225
+            if(stAV::getCodecType(aStream) != AVMEDIA_TYPE_AUDIO) {
226
                 continue;
227
             }
228
 
229
@@ -489,7 +552,7 @@
230
             aLanguage = aStream->language;
231
         #endif
232
             if(aLanguage != aPrefLangAudio
233
-            && myAudio->init(aFormatCtx, aStreamId, "")) {
234
+            && myAudio->init(aFormatCtx, aStreamId, aTitleString)) {
235
                 theInfo.LoadedAudio = anAudioStreamId;
236
                 break;
237
             }
238
@@ -565,6 +628,33 @@
239
         }
240
     }
241
 
242
+    // read general information about streams
243
+    for(size_t aCtxIter = 0; aCtxIter < myCtxList.size(); ++aCtxIter) {
244
+        AVFormatContext* aFormatCtx = myCtxList[aCtxIter];
245
+
246
+        StString aFrmtInfo;
247
+        if(aFormatCtx->bit_rate != 0) {
248
+            aFrmtInfo += StString("bitrate: ") + (int64_t(aFormatCtx->bit_rate) / 1000) + " kb/s";
249
+        }
250
+        if(!aFrmtInfo.isEmpty()) {
251
+            StString aStreamInfoKey = StString("input ") + aCtxIter;
252
+            myFileInfoTmp->Info.add(StArgument(aStreamInfoKey, aFrmtInfo));
253
+        }
254
+
255
+        for(unsigned int aStreamId = 0; aStreamId < aFormatCtx->nb_streams; ++aStreamId) {
256
+            AVStream* aStream = aFormatCtx->streams[aStreamId];
257
+            StString aLang = stAV::meta::readLang(aStream);
258
+            if(aLang.isEmpty()) {
259
+                aLang = "und";
260
+            }
261
+
262
+            StString aStreamInfoKey = StString("steam ")
263
+                                    + (myCtxList.size() > 1 ? (StString() + aCtxIter + ":" + aStreamId) : (StString() + aStreamId))
264
+                                    + " [" + aLang + "]";
265
+            myFileInfoTmp->Info.add(StArgument(aStreamInfoKey, formatStreamInfo(aStream)));
266
+        }
267
+    }
268
+
269
     if(!myVideoMaster->isInitialized() && !myAudio->isInitialized()) {
270
         signals.onError(stCString("FFmpeg: Didn't found any video or audio streams"));
271
         return false;
272
@@ -678,6 +768,15 @@
273
         isSeekDone = doSeekStream(theFormatCtx, myVideoMaster->getId(), theSeekPts, toSeekBack);
274
     } else if(myVideoSlave->isInContext(theFormatCtx)) {
275
         isSeekDone = doSeekStream(theFormatCtx, myVideoSlave->getId(), theSeekPts, toSeekBack);
276
+    } else if(myAudio->isInContext(theFormatCtx)) {
277
+        //
278
+    } else if(mySubtitles->isInContext(theFormatCtx)) {
279
+        if(mySubtitles->getFileName().isEndsWithIgnoreCase(stCString(".srt"))) {
280
+            // workaround SRT seeking issues - make a heavy seek (usual size of SRT file is not greater than 200 KiB)
281
+            isSeekDone = doSeekStream(theFormatCtx, mySubtitles->getId(), 0.0, true);
282
+        } else {
283
+            isSeekDone = doSeekStream(theFormatCtx, mySubtitles->getId(), theSeekPts, toSeekBack);
284
+        }
285
     }
286
     if(!isSeekDone && myAudio->isInContext(theFormatCtx)) {
287
         // if no video stream or seeking was failed - try to seek Audio stream
288
@@ -690,7 +789,12 @@
289
         isSeekDone = av_seek_frame(theFormatCtx, -1, aSeekTarget, aFlags) >= 0;
290
         if(!isSeekDone) {
291
         #ifdef ST_DEBUG
292
-            ST_ERROR_LOG("Disaster! Seeking to " + theSeekPts + " [" + theFormatCtx->filename + "] has failed.");
293
+        #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 7, 100))
294
+            const char* aFileName = theFormatCtx->url;
295
+        #else
296
+            const char* aFileName = theFormatCtx->filename;
297
+        #endif
298
+            ST_ERROR_LOG("Disaster! Seeking to " + theSeekPts + " [" + aFileName + "] has failed.");
299
         #endif
300
         }
301
     }
302
@@ -718,8 +822,8 @@
303
 
304
     if(!isSeekDone) {
305
         ST_DEBUG_LOG("Error while seeking"
306
-                   + (aStream->codec->codec_type == AVMEDIA_TYPE_VIDEO ? " Video"
307
-                   : (aStream->codec->codec_type == AVMEDIA_TYPE_AUDIO ? " Audio" : " "))
308
+                   + (stAV::getCodecType(aStream) == AVMEDIA_TYPE_VIDEO ? " Video"
309
+                   : (stAV::getCodecType(aStream) == AVMEDIA_TYPE_AUDIO ? " Audio" : " "))
310
                    +  "stream to " + theSeekPts + "sec(" + (theSeekPts + stAV::unitsToSeconds(aStream, aStream->start_time)) + "sec)");
311
     }
312
     return isSeekDone;
313
@@ -747,6 +851,7 @@
314
         doFlush();
315
         if(myVideoMaster->isInitialized()) {
316
             const StString   aFileNameMaster = myVideoMaster->getFileName();
317
+            const StString   aFileNameSlave  = myVideoSlave ->getFileName();
318
             AVFormatContext* aCtxMaster      = myVideoMaster->getContext();
319
             const signed int aStreamIdMaster = myVideoMaster->getId();
320
             myVideoMaster->pushEnd();
321
@@ -770,7 +875,7 @@
322
             myVideoMaster->init(aCtxMaster, aStreamIdMaster, aFileNameMaster, myCurrParams);
323
             myVideoMaster->setSlave(NULL);
324
             if(toDecodeSlave) {
325
-                myVideoSlave->init(mySlaveCtx, mySlaveStream, "", myCurrParams);
326
+                myVideoSlave->init(mySlaveCtx, mySlaveStream, aFileNameSlave, myCurrParams);
327
                 myVideoMaster->setSlave(myVideoSlave);
328
             }
329
             myVideoMaster->pushStart();
330
@@ -820,6 +925,7 @@
331
 
332
     StArrayList<StAVPacket> anAVPackets(myCtxList.size());
333
     StArrayList<bool> aQueueIsFull(myCtxList.size());
334
+    StArrayList<bool> aQueueIsEmpty(myCtxList.size());
335
     myPlayCtxList.clear();
336
     size_t anEmptyQueues = 0;
337
     size_t aCtxId = 0;
338
@@ -835,6 +941,7 @@
339
         myPlayCtxList.add(aFormatCtx);
340
         anAVPackets.add(StAVPacket(myCurrParams));
341
         aQueueIsFull.add(false);
342
+        aQueueIsEmpty.add(false);
343
     }
344
 
345
     // reset target FPS
346
@@ -851,6 +958,23 @@
347
                 // read next packet
348
                 if(av_read_frame(aFormatCtx, aPacket.getAVpkt()) < 0) {
349
                     ++anEmptyQueues;
350
+                    if(!aQueueIsEmpty[aCtxId]) {
351
+                        aQueueIsEmpty[aCtxId] = true;
352
+                        // force decoding of last frame
353
+                        const StAVPacket aDummyLastPacket(myCurrParams, StAVPacket::LAST_PACKET);
354
+                        if(myVideoMaster->isInContext(aFormatCtx)) {
355
+                            myVideoMaster->push(aDummyLastPacket);
356
+                        }
357
+                        if(myVideoSlave->isInContext(aFormatCtx)) {
358
+                            myVideoSlave->push(aDummyLastPacket);
359
+                        }
360
+                        if(myAudio->isInContext(aFormatCtx)) {
361
+                            myAudio->push(aDummyLastPacket);
362
+                        }
363
+                        if(mySubtitles->isInContext(aFormatCtx)) {
364
+                            mySubtitles->push(aDummyLastPacket);
365
+                        }
366
+                    }
367
                     continue;
368
                 }
369
             }
370
@@ -949,9 +1073,9 @@
371
                 for(aCtxId = 0; aCtxId < myCtxList.size() && !myAudio->isInitialized(); ++aCtxId) {
372
                     aFormatCtx = myCtxList[aCtxId];
373
                     for(unsigned int aStreamId = 0; aStreamId < aFormatCtx->nb_streams; ++aStreamId) {
374
-                        if(aFormatCtx->streams[aStreamId]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
375
+                        if(stAV::getCodecType(aFormatCtx->streams[aStreamId]) == AVMEDIA_TYPE_AUDIO) {
376
                             if(aCounter == anActiveStreamId) {
377
-                                myAudio->init(aFormatCtx, aStreamId, "");
378
+                                myAudio->init(aFormatCtx, aStreamId, myFileList[aCtxId]);
379
                                 myAudio->pushStart();
380
                                 break;
381
                             }
382
@@ -1003,9 +1127,9 @@
383
                 for(aCtxId = 0; aCtxId < myCtxList.size() && !mySubtitles->isInitialized(); ++aCtxId) {
384
                     aFormatCtx = myCtxList[aCtxId];
385
                     for(unsigned int aStreamId = 0; aStreamId < aFormatCtx->nb_streams; ++aStreamId) {
386
-                        if(aFormatCtx->streams[aStreamId]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
387
+                        if(stAV::getCodecType(aFormatCtx->streams[aStreamId]) == AVMEDIA_TYPE_SUBTITLE) {
388
                             if(aCounter == anActiveStreamId) {
389
-                                mySubtitles->init(aFormatCtx, aStreamId, "");
390
+                                mySubtitles->init(aFormatCtx, aStreamId, myFileList[aCtxId]);
391
                                 mySubtitles->pushStart();
392
                                 break;
393
                             }
394
@@ -1058,6 +1182,7 @@
395
     #endif
396
 
397
         // All packets sent
398
+        bool isPendingPlayNext = false;
399
         if(anEmptyQueues == myPlayCtxList.size()) {
400
             bool areFlushed = false;
401
             // It seems FFmpeg fail to seek the stream after all packets were read...
402
@@ -1068,26 +1193,55 @@
403
                || !mySubtitles->isEmpty()   || !mySubtitles->isInDowntime()) {
404
                 StThread::sleep(10);
405
                 if(!areFlushed && (popPlayEvent(aSeekPts, toSeekBack) == ST_PLAYEVENT_NEXT)) {
406
+                    isPendingPlayNext = true;
407
                     doFlush();
408
                     if(myAudio->isInitialized()) {
409
                         myAudio->pushPlayEvent(ST_PLAYEVENT_SEEK, 0.0);
410
                     }
411
                     areFlushed = true;
412
+                    isPendingPlayNext = true;
413
                 }
414
             }
415
             // If video is played - always wait until audio played
416
-            if(myVideoMaster->isInitialized() && myAudio->isInitialized()) {
417
-                while(myAudio->stalIsAudioPlaying()) {
418
-                    StThread::sleep(10);
419
-                    if(!areFlushed && (popPlayEvent(aSeekPts, toSeekBack) == ST_PLAYEVENT_NEXT)) {
420
-                        doFlush();
421
-                        if(myAudio->isInitialized()) {
422
-                            myAudio->pushPlayEvent(ST_PLAYEVENT_SEEK, 0.0);
423
+            if(myVideoMaster->isInitialized()) {
424
+                if(myAudio->isInitialized()) {
425
+                    while(myAudio->stalIsAudioPlaying()) {
426
+                        StThread::sleep(10);
427
+                        if(!areFlushed && (popPlayEvent(aSeekPts, toSeekBack) == ST_PLAYEVENT_NEXT)) {
428
+                            isPendingPlayNext = true;
429
+                            doFlush();
430
+                            if(myAudio->isInitialized()) {
431
+                                myAudio->pushPlayEvent(ST_PLAYEVENT_SEEK, 0.0);
432
+                            }
433
+                            areFlushed = true;
434
+                            isPendingPlayNext = true;
435
+                            break;
436
+                        }
437
+                    }
438
+                } else if(myDuration < (double )params.SlideShowDelay->getValue()) {
439
+                    StTimer aDelayTimer;
440
+                    aDelayTimer.restart(myDuration * 1000.0);
441
+                    while(aDelayTimer.getElapsedTimeInSec() < (double )params.SlideShowDelay->getValue()) {
442
+                        StThread::sleep(10);
443
+                        if((popPlayEvent(aSeekPts, toSeekBack) == ST_PLAYEVENT_NEXT)) {
444
+                            isPendingPlayNext = true;
445
+                            break;
446
+                        }
447
+                        const bool isPaused = !isPlaying();
448
+                        if(isPaused) {
449
+                            aDelayTimer.pause();
450
+                        } else {
451
+                            aDelayTimer.resume();
452
                         }
453
-                        areFlushed = true;
454
                     }
455
                 }
456
             }
457
+            if(isPendingPlayNext) {
458
+                // resend event after it was pop out
459
+                pushPlayEvent(ST_PLAYEVENT_NEXT);
460
+                break;
461
+            }
462
+
463
             // end when any one in format context finished
464
             myCurrParams->Timestamp = 0.0f;
465
             break;
466
@@ -1100,7 +1254,7 @@
467
     if(myAudio->isInitialized())       myAudio->pushEnd();
468
     if(mySubtitles->isInitialized())   mySubtitles->pushEnd();
469
 
470
-    // what for queues receive 'end-packet'
471
+    // wait for queues receive 'end-packet'
472
     while(!myVideoMaster->isEmpty() || !myVideoMaster->isInDowntime()
473
        || !myAudio->isEmpty()       || !myAudio->isInDowntime()
474
        || !myVideoSlave->isEmpty()  || !myVideoSlave->isInDowntime()
475
@@ -1146,20 +1300,20 @@
476
         dataResult->initWrapper(dataLeft);
477
     }
478
 
479
-    StString title = myLangMap->getValue(StMoviePlayerStrings::DIALOG_SAVE_SNAPSHOT);
480
-    StMIMEList filter;
481
+    StOpenFileName anOpenInfo;
482
+    anOpenInfo.Title = myLangMap->getValue(StMoviePlayerStrings::DIALOG_SAVE_SNAPSHOT);
483
     StString saveExt;
484
     if(toSaveStereo) {
485
         switch(theImgType) {
486
             case StImageFile::ST_TYPE_PNG:
487
                 saveExt = "pns";
488
-                filter.add(StMIME("image/pns", saveExt,
489
-                                  "PNS - png  stereo image, lossless"));
490
+                anOpenInfo.Filter.add(StMIME("image/pns", saveExt,
491
+                                             "PNS - png  stereo image, lossless"));
492
                 break;
493
             case StImageFile::ST_TYPE_JPEG:
494
                 saveExt = "jps";
495
-                filter.add(StMIME("image/jps", saveExt,
496
-                                  "JPS - jpeg stereo image, lossy"));
497
+                anOpenInfo.Filter.add(StMIME("image/jps", saveExt,
498
+                                             "JPS - jpeg stereo image, lossy"));
499
                 break;
500
             default:
501
                 return false;
502
@@ -1168,13 +1322,13 @@
503
         switch(theImgType) {
504
             case StImageFile::ST_TYPE_PNG:
505
                 saveExt = "png";
506
-                filter.add(StMIME("image/png", saveExt,
507
-                                  "PNG image, lossless"));
508
+                anOpenInfo.Filter.add(StMIME("image/png", saveExt,
509
+                                             "PNG image, lossless"));
510
                 break;
511
             case StImageFile::ST_TYPE_JPEG:
512
                 saveExt = "jpg";
513
-                filter.add(StMIME("image/jpg", saveExt,
514
-                                  "JPEG image, lossy"));
515
+                anOpenInfo.Filter.add(StMIME("image/jpg", saveExt,
516
+                                             "JPEG image, lossy"));
517
                 break;
518
             default:
519
                 return false;
520
@@ -1182,7 +1336,8 @@
521
     }
522
 
523
     StString fileToSave;
524
-    if(StFileNode::openFileDialog(myCurrNode->getFolderPath(), title, filter, fileToSave, true)) {
525
+    anOpenInfo.Folder = myCurrNode->getFolderPath();
526
+    if(StFileNode::openFileDialog(fileToSave, anOpenInfo, true)) {
527
         if(StFileNode::getExtension(fileToSave) != saveExt) {
528
             fileToSave += StString('.') + saveExt;
529
         }
530
@@ -1252,6 +1407,7 @@
531
         // wait for initial message
532
         waitEvent();
533
         if(toQuit) {
534
+            close();
535
             myQuitEvent.set();
536
             return;
537
         }
538
@@ -1270,12 +1426,12 @@
539
 
540
         if(myVideoMaster->isInContext(myCtxList[0])) {
541
             myVideoTimer = new StVideoTimer(myVideoMaster, myAudio,
542
-                1000.0 * av_q2d(myCtxList[0]->streams[myVideoMaster->getId()]->codec->time_base));
543
+                1000.0 * av_q2d(stAV::getCodecCtx(myCtxList[0]->streams[myVideoMaster->getId()])->time_base));
544
             myVideoTimer->setAudioDelay(myAudioDelayMSec);
545
             myVideoTimer->setBenchmark(myIsBenchmark);
546
         } else if(myCtxList.size() > 1 && myVideoMaster->isInContext(myCtxList[1])) {
547
             myVideoTimer = new StVideoTimer(myVideoMaster, myAudio,
548
-                1000.0 * av_q2d(myCtxList[1]->streams[myVideoMaster->getId()]->codec->time_base));
549
+                1000.0 * av_q2d(stAV::getCodecCtx(myCtxList[1]->streams[myVideoMaster->getId()])->time_base));
550
             myVideoTimer->setAudioDelay(myAudioDelayMSec);
551
             myVideoTimer->setBenchmark(myIsBenchmark);
552
         } else {
553
@@ -1311,6 +1467,9 @@
554
                 myPlayList->walkToNext(false);
555
             }
556
             if(toQuit) {
557
+                // make sure to close AVIO contexts from the same working thread,
558
+                // because some of them can be attached to specific thread (like StAVIOJniHttpContext to JavaVM)
559
+                close();
560
                 myQuitEvent.set();
561
                 return;
562
             }
563
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideo.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideo.h Changed
78
 
1
@@ -91,18 +91,15 @@
2
         public: //! @name public methods
3
 
4
     static const char* ST_VIDEOS_MIME_STRING;
5
+    static const char* ST_IMAGES_MIME_STRING;
6
 
7
-    ST_LOCAL const StMIMEList& getMimeListVideo() const {
8
-        return myMimesVideo;
9
-    }
10
+    ST_LOCAL const StMIMEList& getMimeListVideo() const { return myMimesVideo; }
11
 
12
-    ST_LOCAL const StMIMEList& getMimeListAudio() const {
13
-        return myMimesAudio;
14
-    }
15
+    ST_LOCAL const StMIMEList& getMimeListAudio() const { return myMimesAudio; }
16
 
17
-    ST_LOCAL const StMIMEList& getMimeListSubtitles() const {
18
-        return myMimesSubs;
19
-    }
20
+    ST_LOCAL const StMIMEList& getMimeListSubtitles() const { return myMimesSubs; }
21
+
22
+    ST_LOCAL const StMIMEList& getMimeListImages() const { return myMimesImages; }
23
 
24
     /**
25
      * Main constructor.
26
@@ -165,6 +162,13 @@
27
     }
28
 
29
     /**
30
+     * Set theater mode.
31
+     */
32
+    ST_LOCAL void setTheaterMode(bool theIsTheater) {
33
+        myVideoMaster->setTheaterMode(theIsTheater);
34
+    }
35
+
36
+    /**
37
      * Stick to panorama 360 mode.
38
      */
39
     ST_LOCAL void setStickPano360(bool theToStick) {
40
@@ -172,6 +176,11 @@
41
     }
42
 
43
     /**
44
+     * Set if JPS file should be read as Left/Right (TRUE) of as Right/Left (FALSE).
45
+     */
46
+    ST_LOCAL void setSwapJPS(bool theToSwap) { myVideoMaster->setSwapJPS(theToSwap); }
47
+
48
+    /**
49
      * Retrieve information about currently played file.
50
      */
51
     ST_LOCAL StHandle<StMovieInfo> getFileInfo(const StHandle<StStereoParams>& theParams) const;
52
@@ -264,6 +273,7 @@
53
         StHandle<StBoolParam>         UseOpenJpeg;     //!< use OpenJPEG (libopenjpeg) instead of built-in jpeg2000 decoder
54
         StHandle<StBoolParam>         ToSearchSubs;    //!< automatically search for additional subtitles/audio track files nearby video file
55
         StHandle<StBoolParamNamed>    ToTrackHeadAudio;//!< enable/disable head-tracking for audio listener
56
+        StHandle<StFloat32Param>      SlideShowDelay;  //!< slideshow delay
57
         StHandle<StParamActiveStream> activeAudio;     //!< active Audio stream
58
         StHandle<StParamActiveStream> activeSubtitles; //!< active Subtitles stream
59
 
60
@@ -368,6 +378,9 @@
61
      */
62
     ST_LOCAL void close();
63
 
64
+    /**
65
+     * Dispatch packets from format contexts to decoding queues.
66
+     */
67
     ST_LOCAL void packetsLoop();
68
 
69
     /**
70
@@ -432,6 +445,7 @@
71
     StMIMEList                    myMimesVideo;
72
     StMIMEList                    myMimesAudio;
73
     StMIMEList                    myMimesSubs;
74
+    StMIMEList                    myMimesImages;
75
     StHandle<StThread>            myThread;      //!< main loop thread
76
     StHandle<StResourceManager>   myResMgr;      //!< resource manager
77
     StHandle<StTranslations>      myLangMap;     //!< translations dictionary
78
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideoDxva2.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideoDxva2.cpp Changed
90
 
1
@@ -131,7 +131,7 @@
2
     /**
3
      * Destroy decoder.
4
      */
5
-    virtual void decoderDestroy() ST_ATTR_OVERRIDE {
6
+    virtual void decoderDestroy(AVCodecContext* ) ST_ATTR_OVERRIDE {
7
         myPoolsTmp[0].release();
8
         myPoolsTmp[1].release();
9
         myPoolsTmp[2].release();
10
@@ -229,7 +229,7 @@
11
 };
12
 
13
 void StDxva2Context::release() {
14
-    decoderDestroy();
15
+    decoderDestroy(NULL);
16
     if(myDecoderService != NULL) {
17
         myDecoderService->Release();
18
         myDecoderService = NULL;
19
@@ -497,14 +497,14 @@
20
 bool StDxva2Context::decoderCreate(StVideoQueue&   theVideo,
21
                                    AVCodecContext* theCodecCtx) {
22
     const StSignal<void (const StCString& )>& onError = theVideo.signals.onError;
23
-    decoderDestroy();
24
+    decoderDestroy(theCodecCtx);
25
     theCodecCtx->hwaccel_context = NULL;
26
 
27
     uint32_t aNbGuids  = 0;
28
     GUID*    aGuidList = NULL;
29
     if(myDecoderService->GetDecoderDeviceGuids(&aNbGuids, &aGuidList) != S_OK) {
30
         onError(stCString("StVideoQueue: Failed to retrieve decoder DXVA2 device GUIDs"));
31
-        decoderDestroy();
32
+        decoderDestroy(theCodecCtx);
33
         return false;
34
     }
35
 
36
@@ -550,7 +550,7 @@
37
 
38
     if(::IsEqualGUID(aDeviceGuid, GUID_NULL)) {
39
         onError(stCString("StVideoQueue: No DXVA2 decoder device for codec found"));
40
-        decoderDestroy();
41
+        decoderDestroy(theCodecCtx);
42
         return false;
43
     }
44
 
45
@@ -565,7 +565,7 @@
46
     DXVA2_ConfigPictureDecode  aBestCfg = {{0}};
47
     if(myDecoderService->GetDecoderConfigurations(aDeviceGuid, &aDesc, NULL, &aNbConfigs, &aCfgList) != S_OK) {
48
         onError(stCString("StVideoQueue: Unable to retrieve DXVA2 decoder configurations"));
49
-        decoderDestroy();
50
+        decoderDestroy(theCodecCtx);
51
         return false;
52
     }
53
 
54
@@ -592,7 +592,7 @@
55
     ::CoTaskMemFree(aCfgList);
56
     if(aBestScore == 0) {
57
         onError(stCString("StVideoQueue: No valid DXVA2 decoder configuration available"));
58
-        decoderDestroy();
59
+        decoderDestroy(theCodecCtx);
60
         return false;
61
     }
62
 
63
@@ -628,7 +628,7 @@
64
     if(myD3dSurfaces == NULL
65
     || mySurfInfos   == NULL) {
66
         ST_ERROR_LOG(stCString("StVideoQueue: Unable to allocate surface arrays"));
67
-        decoderDestroy();
68
+        decoderDestroy(theCodecCtx);
69
         return false;
70
     }
71
 
72
@@ -640,7 +640,7 @@
73
                                                      myD3dSurfaces, NULL);
74
     if(anHRes != S_OK) {
75
         onError(StString("StVideoQueue: Failed to create ") + myNbSurfaces + " video surfaces");
76
-        decoderDestroy();
77
+        decoderDestroy(theCodecCtx);
78
         return false;
79
     }
80
 
81
@@ -649,7 +649,7 @@
82
                                                   myNbSurfaces, &myDxvaDecoder);
83
     if(anHRes != S_OK) {
84
         onError(stCString("StVideoQueue: Failed to create DXVA2 video decoder"));
85
-        decoderDestroy();
86
+        decoderDestroy(theCodecCtx);
87
         return false;
88
     }
89
 
90
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideoQueue.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideoQueue.cpp Changed
970
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -28,16 +28,6 @@
9
 
10
 namespace {
11
 
12
-#if defined(__APPLE__) || defined(__ANDROID__)
13
-    /**
14
-     * Override pixel format.
15
-     */
16
-    AVPixelFormat stGetFormatYUV420P(AVCodecContext*      /*theCtx*/,
17
-                                     const AVPixelFormat* /*theFmt*/) {
18
-        return stAV::PIX_FMT::YUV420P;
19
-    }
20
-#endif
21
-
22
 #if(LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 0, 0))
23
     /**
24
      * Release the frame buffer (old API).
25
@@ -70,7 +60,7 @@
26
         return avcodec_default_get_format(myCodecCtx, theFormats);
27
     }
28
 
29
-    for(const AVPixelFormat* aFormatIter = theFormats; *aFormatIter != -1; ++aFormatIter) {
30
+    for(const AVPixelFormat* aFormatIter = theFormats; *aFormatIter != stAV::PIX_FMT::NONE; ++aFormatIter) {
31
         /*const AVPixFmtDescriptor* aDesc = av_pix_fmt_desc_get(*aFormatIter);
32
         if(!(aDesc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
33
             return *aFormatIter;
34
@@ -84,6 +74,19 @@
35
             }
36
             return *aFormatIter;
37
         }
38
+    #elif defined(__APPLE__)
39
+        if(*aFormatIter == stAV::PIX_FMT::VIDEOTOOLBOX_VLD) {
40
+            if(!hwaccelInit()) {
41
+                myIsGpuFailed = true;
42
+                return avcodec_default_get_format(myCodecCtx, theFormats);
43
+            }
44
+            return *aFormatIter;
45
+        }
46
+    #elif defined(__ANDROID__)
47
+        if(*aFormatIter == AV_PIX_FMT_MEDIACODEC) {
48
+            // decoding into surface (like android.graphics.SurfaceTexture) is not yet support
49
+            return *aFormatIter;
50
+        }
51
     #endif
52
     }
53
 
54
@@ -104,6 +107,15 @@
55
             }
56
             isDone  = true;
57
         }
58
+    /*#elif defined(__APPLE__) // standard FFmpeg VideoToolbox wrapper is used - action is not needed
59
+        if(theFrame->format == stAV::PIX_FMT::VIDEOTOOLBOX_VLD) {
60
+            if(!myHWAccelCtx.isNull()) {
61
+                aResult = myHWAccelCtx->getFrameBuffer(*this, theFrame);
62
+            } else {
63
+                aResult = -1;
64
+            }
65
+            isDone  = true;
66
+        }*/
67
     #endif
68
         if(!isDone) {
69
             aResult = avcodec_default_get_buffer2(myCodecCtx, theFrame, theFlags);
70
@@ -134,7 +146,7 @@
71
     return aResult;
72
 }
73
 
74
-#if !defined(_WIN32)
75
+#if !defined(_WIN32) && !defined(__APPLE__)
76
 bool StVideoQueue::hwaccelInit() { return false; }
77
 #endif
78
 
79
@@ -156,10 +168,10 @@
80
   myTextureQueue(theTextureQueue),
81
   myHasDataState(false),
82
   myMaster(theMaster),
83
-#if defined(__APPLE__)
84
-  myCodecH264HW(avcodec_find_decoder_by_name("h264_vda")),
85
-#elif defined(__ANDROID__)
86
+#if defined(__ANDROID__)
87
   myCodecH264HW(avcodec_find_decoder_by_name("h264_mediacodec")),
88
+  myCodecHevcHW(avcodec_find_decoder_by_name("hevc_mediacodec")),
89
+  myCodecVp9HW (avcodec_find_decoder_by_name("vp9_mediacodec")),
90
 #endif
91
   myCodecOpenJpeg(avcodec_find_decoder_by_name("libopenjpeg")),
92
   myUseGpu(false),
93
@@ -187,7 +199,9 @@
94
   myStFormatByUser(StFormat_AUTO),
95
   myStFormatByName(StFormat_AUTO),
96
   myStFormatInStream(StFormat_AUTO),
97
-  myToStickPano360(false) {
98
+  myIsTheaterMode(false),
99
+  myToStickPano360(false),
100
+  myToSwapJps(false) {
101
 #ifdef ST_USE64PTR
102
     myFrame.Frame->opaque = (void* )stAV::NOPTS_VALUE;
103
 #else
104
@@ -256,10 +270,31 @@
105
                              const bool theToUseGpu) {
106
     // close previous codec
107
     if(myCodec != NULL) {
108
-        avcodec_close(myCodecCtx);
109
+        myCodec = NULL;
110
         fillCodecInfo(NULL);
111
+    #ifdef ST_AV_NEWCODECPAR
112
+        avcodec_free_context(&myCodecCtx);
113
+        myCodecCtx = avcodec_alloc_context3(NULL);
114
+        if(avcodec_parameters_to_context(myCodecCtx, myStream->codecpar) < 0) {
115
+            signals.onError(stCString("Internal error: unable to copy codec parameters"));
116
+            return false;
117
+        }
118
+    #else
119
+        avcodec_close(myCodecCtx);
120
+    #endif
121
     }
122
-    myCodec = NULL;
123
+
124
+    myCodecCtx->opaque         = this;
125
+    myCodecCtx->get_format     = stGetFrameFormat;
126
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
127
+    if(check720in1080()) {
128
+        myCodecCtx->flags2 |= AV_CODEC_FLAG2_IGNORE_CROP;
129
+    }
130
+    myCodecCtx->get_buffer2    = stGetFrameBuffer2;
131
+#else
132
+    myCodecCtx->get_buffer     = stGetFrameBuffer1;
133
+    myCodecCtx->release_buffer = stReleaseFrameBuffer;
134
+#endif
135
 
136
     // configure the codec
137
     myCodecCtx->codec_id = theCodec->id;
138
@@ -268,7 +303,10 @@
139
     av_dict_set(&anOpts, "refcounted_frames", "1", 0);
140
 #endif
141
 
142
-    int aNbThreads = theToUseGpu ? 1 : StThread::countLogicalProcessors();
143
+    // attached pics are sparse, therefore we would not want to delay their decoding till EOF
144
+    int aNbThreads = theToUseGpu || isAttachedPicture()
145
+                   ? 1
146
+                   : StThread::countLogicalProcessors();
147
     myCodecCtx->thread_count = aNbThreads;
148
 #if(LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 112, 0))
149
     avcodec_thread_init(myCodecCtx, aNbThreads);
150
@@ -293,71 +331,48 @@
151
                         const unsigned int theStreamId,
152
                         const StString&    theFileName,
153
                         const StHandle<StStereoParams>& theNewParams) {
154
-    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)
155
-    || myCodecCtx->codec_type != AVMEDIA_TYPE_VIDEO) {
156
+    if(!StAVPacketQueue::init(theFormatCtx, theStreamId, theFileName)) {
157
         signals.onError(stCString("FFmpeg: invalid stream"));
158
         deinit();
159
         return false;
160
     }
161
 
162
-    // detect 720in1080 streams with cropping information
163
-    const bool is720in1080 = (sizeX() == 1280) && (sizeY() == 720)
164
-                          && (getCodedSizeX() == 1920)
165
-                          && (getCodedSizeY() == 1080 || getCodedSizeY() == 1088);
166
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
167
-    if(is720in1080) {
168
-        myCodecCtx->flags2 |= CODEC_FLAG2_IGNORE_CROP;
169
-    }
170
-#endif
171
-
172
-    // find the decoder for the video stream
173
-    myCodecCtx->opaque         = this;
174
-    myCodecCtx->get_format     = stGetFrameFormat;
175
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
176
-    myCodecCtx->get_buffer2    = stGetFrameBuffer2;
177
-#else
178
-    myCodecCtx->get_buffer     = stGetFrameBuffer1;
179
-    myCodecCtx->release_buffer = stReleaseFrameBuffer;
180
-#endif
181
-
182
-    myCodecAuto = avcodec_find_decoder(myCodecCtx->codec_id);
183
-    if(myCodecAuto == NULL) {
184
-        signals.onError(stCString("FFmpeg: Video codec not found"));
185
-        deinit();
186
-        return false;
187
-    }
188
-
189
 #if defined(_WIN32)
190
-    myIsGpuFailed = myCodecCtx->codec_id != CodecIdMPEG2
191
-                 && myCodecCtx->codec_id != CodecIdH264
192
-                 && myCodecCtx->codec_id != CodecIdVC1
193
-                 && myCodecCtx->codec_id != CodecIdWMV3
194
-                 && myCodecCtx->codec_id != CodecIdVC1
195
-                 && myCodecCtx->codec_id != CodecIdHEVC;
196
+    myIsGpuFailed = myCodecAutoId != CodecIdMPEG2
197
+                 && myCodecAutoId != CodecIdH264
198
+                 && myCodecAutoId != CodecIdVC1
199
+                 && myCodecAutoId != CodecIdWMV3
200
+                 && myCodecAutoId != CodecIdHEVC;
201
+#elif defined(__APPLE__)
202
+    myIsGpuFailed = myCodecAutoId != CodecIdMPEG2
203
+                 && myCodecAutoId != CodecIdH264
204
+                 && myCodecAutoId != CodecIdHEVC;
205
 #endif
206
 
207
     bool isCodecOverridden = false;
208
     if(myUseOpenJpeg
209
-    && myCodecCtx->codec_id == CodecIdJpeg2K
210
+    && myCodecAutoId == CodecIdJpeg2K
211
     && myCodecOpenJpeg != NULL) {
212
         isCodecOverridden = initCodec(myCodecOpenJpeg, false);
213
     }
214
 
215
     // open VIDEO codec
216
-#if defined(__APPLE__) || defined(__ANDROID__)
217
+#if defined(__ANDROID__)
218
     AVCodec* aCodecGpu = NULL;
219
     if(myUseGpu
220
-    && StString(myCodecAuto->name).isEquals(stCString("h264"))
221
     && myCodecCtx->pix_fmt == stAV::PIX_FMT::YUV420P) {
222
-        aCodecGpu = myCodecH264HW;
223
+        const StString anAutoCodecName(myCodecAuto->name);
224
+        if(anAutoCodecName.isEquals(stCString("h264"))) {
225
+            aCodecGpu = myCodecH264HW;
226
+        } else if(anAutoCodecName.isEquals(stCString("hevc"))) {
227
+            aCodecGpu = myCodecHevcHW;
228
+        } else if(anAutoCodecName.isEquals(stCString("vp9"))) {
229
+            aCodecGpu = myCodecVp9HW;
230
+        }
231
     }
232
 
233
     if(aCodecGpu != NULL) {
234
-        myCodecCtx->get_format = stGetFormatYUV420P;
235
         isCodecOverridden = initCodec(aCodecGpu, true);
236
-        if(!isCodecOverridden) {
237
-            myCodecCtx->get_format = myGetFrmtInit;
238
-        }
239
     }
240
     if(!isCodecOverridden && !initCodec(myCodecAuto, false)) {
241
         signals.onError(stCString("FFmpeg: Could not open video codec"));
242
@@ -383,7 +398,7 @@
243
     myFrame.reset();
244
 
245
     // compute PAR
246
-    if(myStream->sample_aspect_ratio.num && av_cmp_q(myStream->sample_aspect_ratio, myStream->codec->sample_aspect_ratio)) {
247
+    if(myStream->sample_aspect_ratio.num && av_cmp_q(myStream->sample_aspect_ratio, myCodecCtx->sample_aspect_ratio)) {
248
         myPixelRatio = GLfloat(myStream->sample_aspect_ratio.num) / GLfloat(myStream->sample_aspect_ratio.den);
249
     } else {
250
         if(myCodecCtx->sample_aspect_ratio.num == 0 ||
251
@@ -422,6 +437,10 @@
252
         switch(aSpherical->projection) {
253
             case AV_SPHERICAL_EQUIRECTANGULAR: {
254
                 theNewParams->ViewingMode = StViewSurface_Sphere;
255
+                if(sizeX() == sizeY()) {
256
+                    // TODO - hemisphere information should be somewhere in the file
257
+                    //theNewParams->ViewingMode = StViewSurface_Hemisphere;
258
+                }
259
                 break;
260
             }
261
             case AV_SPHERICAL_CUBEMAP: {
262
@@ -429,6 +448,7 @@
263
                 //spherical->padding
264
                 break;
265
             }
266
+            //case AV_SPHERICAL_MESH: { theNewParams->ViewingMode = StViewSurface_CubemapEAC; break; }
267
             case AV_SPHERICAL_EQUIRECTANGULAR_TILE: {
268
                 // unsupported
269
                 //av_spherical_tile_bounds(aSpherical, par->width, par->height, &l, &t, &r, &b);
270
@@ -461,7 +481,7 @@
271
 #endif
272
 
273
     // stereoscopic mode tags
274
-    myStFormatInStream = is720in1080 ? StFormat_Tiled4x : StFormat_AUTO;
275
+    myStFormatInStream = check720in1080() ? StFormat_Tiled4x : StFormat_AUTO;
276
     if(stAV::meta::readTag(myFormatCtx, THE_SRC_MODE_KEY,     aValue)
277
     || stAV::meta::readTag(myStream,    THE_SRC_MODE_KEY,     aValue)
278
     || stAV::meta::readTag(myFormatCtx, THE_SRC_MODE_KEY_WMV, aValue)) {
279
@@ -479,7 +499,7 @@
280
 
281
     // detect information from file name
282
     bool isAnamorphByName = false;
283
-    myStFormatByName = st::formatFromName(myFileName, isAnamorphByName);
284
+    myStFormatByName = st::formatFromName(myFileName, myToSwapJps, isAnamorphByName);
285
     if(myStFormatInStream == StFormat_AUTO
286
     && isAnamorphByName) {
287
         if(myStFormatByName == StFormat_SideBySide_LR
288
@@ -512,17 +532,16 @@
289
     myFramesCounter = 1;
290
     myCachedFrame.nullify();
291
 
292
-    if(myCodecCtx  != NULL
293
-    && myCodecAuto != NULL) {
294
-        myCodecCtx->codec_id = myCodecAuto->id;
295
-    }
296
+#if !defined(ST_AV_NEWCODECPAR)
297
+    if(myCodecCtx != NULL) { myCodecCtx->codec_id = myCodecAutoId; }
298
+#endif
299
     StAVPacketQueue::deinit();
300
+    if(!myHWAccelCtx.isNull()) {
301
+        myHWAccelCtx->decoderDestroy(myCodecCtx);
302
+    }
303
     if(myCodecCtx != NULL) {
304
         myCodecCtx->hwaccel_context = NULL;
305
     }
306
-    if(!myHWAccelCtx.isNull()) {
307
-        myHWAccelCtx->decoderDestroy();
308
-    }
309
 }
310
 
311
 #ifdef ST_AV_OLDSYNC
312
@@ -551,20 +570,33 @@
313
     stAV::dimYUV  aDimsYUV;
314
     myFrame.getImageInfo(myCodecCtx, aFrameSizeX, aFrameSizeY, aPixFmt);
315
     myDataAdp.setBufferCounter(NULL);
316
-    if(aPixFmt == stAV::PIX_FMT::XYZ12) {
317
+    if(aPixFmt == stAV::PIX_FMT::XYZ12
318
+    && myTextureQueue->getDeviceCaps().isSupportedFormat(StImagePlane::ImgRGB48)) {
319
         myDataAdp.setColorModel(StImage::ImgColor_XYZ);
320
         myDataAdp.setColorScale(StImage::ImgScale_Full);
321
         myDataAdp.setPixelRatio(getPixelRatio());
322
         myDataAdp.changePlane(0).initWrapper(StImagePlane::ImgRGB48, myFrame.getPlane(0),
323
                                              size_t(aFrameSizeX), size_t(aFrameSizeY),
324
                                              myFrame.getLineSize(0));
325
-    } else if(aPixFmt == stAV::PIX_FMT::RGB24) {
326
+        return;
327
+    } else if(aPixFmt == stAV::PIX_FMT::RGB24
328
+           && myTextureQueue->getDeviceCaps().isSupportedFormat(StImagePlane::ImgRGB)) {
329
         myDataAdp.setColorModel(StImage::ImgColor_RGB);
330
         myDataAdp.setColorScale(StImage::ImgScale_Full);
331
         myDataAdp.setPixelRatio(getPixelRatio());
332
         myDataAdp.changePlane(0).initWrapper(StImagePlane::ImgRGB, myFrame.getPlane(0),
333
                                              size_t(aFrameSizeX), size_t(aFrameSizeY),
334
                                              myFrame.getLineSize(0));
335
+        return;
336
+    } else if(aPixFmt == stAV::PIX_FMT::RGBA32
337
+           && myTextureQueue->getDeviceCaps().isSupportedFormat(StImagePlane::ImgRGBA)) {
338
+        myDataAdp.setColorModel(StImage::ImgColor_RGBA);
339
+        myDataAdp.setColorScale(StImage::ImgScale_Full);
340
+        myDataAdp.setPixelRatio(getPixelRatio());
341
+        myDataAdp.changePlane(0).initWrapper(StImagePlane::ImgRGBA, myFrame.getPlane(0),
342
+                                             size_t(aFrameSizeX), size_t(aFrameSizeY),
343
+                                             myFrame.getLineSize(0));
344
+        return;
345
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 5, 0))
346
     } else if(stAV::isFormatYUVPlanar(myFrame.Frame,
347
 #else
348
@@ -603,17 +635,25 @@
349
         } else if(aDimsYUV.bitsPerComp == 16) {
350
             aPlaneFrmt = StImagePlane::ImgGray16;
351
         }
352
-        myDataAdp.setColorModel(StImage::ImgColor_YUV);
353
-        myDataAdp.setPixelRatio(getPixelRatio());
354
-        myDataAdp.changePlane(0).initWrapper(aPlaneFrmt, myFrame.getPlane(0),
355
-                                             size_t(aDimsYUV.widthY), size_t(aDimsYUV.heightY), myFrame.getLineSize(0));
356
-        myDataAdp.changePlane(1).initWrapper(aPlaneFrmt, myFrame.getPlane(1),
357
-                                             size_t(aDimsYUV.widthU), size_t(aDimsYUV.heightU), myFrame.getLineSize(1));
358
-        myDataAdp.changePlane(2).initWrapper(aPlaneFrmt, myFrame.getPlane(2),
359
-                                             size_t(aDimsYUV.widthV), size_t(aDimsYUV.heightV), myFrame.getLineSize(2));
360
 
361
-        myFrameBufRef->moveReferenceFrom(myFrame.Frame);
362
-        myDataAdp.setBufferCounter(myFrameBufRef);
363
+        if(myTextureQueue->getDeviceCaps().isSupportedFormat(aPlaneFrmt)) {
364
+            myDataAdp.setColorModel(aDimsYUV.hasAlpha ? StImage::ImgColor_YUVA : StImage::ImgColor_YUV);
365
+            myDataAdp.setPixelRatio(getPixelRatio());
366
+            myDataAdp.changePlane(0).initWrapper(aPlaneFrmt, myFrame.getPlane(0),
367
+                                                 size_t(aDimsYUV.widthY), size_t(aDimsYUV.heightY), myFrame.getLineSize(0));
368
+            myDataAdp.changePlane(1).initWrapper(aPlaneFrmt, myFrame.getPlane(1),
369
+                                                 size_t(aDimsYUV.widthU), size_t(aDimsYUV.heightU), myFrame.getLineSize(1));
370
+            myDataAdp.changePlane(2).initWrapper(aPlaneFrmt, myFrame.getPlane(2),
371
+                                                 size_t(aDimsYUV.widthV), size_t(aDimsYUV.heightV), myFrame.getLineSize(2));
372
+            if(aDimsYUV.hasAlpha) {
373
+                myDataAdp.changePlane(3).initWrapper(aPlaneFrmt, myFrame.getPlane(3),
374
+                                                     size_t(aDimsYUV.widthY), size_t(aDimsYUV.heightY), myFrame.getLineSize(3));
375
+            }
376
+
377
+            myFrameBufRef->moveReferenceFrom(myFrame.Frame);
378
+            myDataAdp.setBufferCounter(myFrameBufRef);
379
+            return;
380
+        }
381
     } else if(aPixFmt == stAV::PIX_FMT::NV12) {
382
         aDimsYUV.isFullScale = false;
383
     #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 29, 0))
384
@@ -632,7 +672,10 @@
385
 
386
         myFrameBufRef->moveReferenceFrom(myFrame.Frame);
387
         myDataAdp.setBufferCounter(myFrameBufRef);
388
-    } else if(!myToRgbIsBroken) {
389
+        return;
390
+    }
391
+
392
+    if(!myToRgbIsBroken) {
393
         if(myToRgbCtx    == NULL
394
         || myToRgbPixFmt != aPixFmt
395
         || size_t(aFrameSizeX) != myDataRGB.getSizeX()
396
@@ -656,16 +699,22 @@
397
                 signals.onError(stCString("FFmpeg: Failed to create SWScaler context"));
398
                 myToRgbIsBroken = true;
399
             } else {
400
-                // assign appropriate parts of RGB buffer to image planes in myFrameRGB
401
-                const size_t aBufferSize = avpicture_get_size(stAV::PIX_FMT::RGB24, aFrameSizeX, aFrameSizeY);
402
-                if(aBufferSize == 0
403
-                || !myDataRGB.initTrash(StImagePlane::ImgRGB, size_t(aFrameSizeX), size_t(aFrameSizeY),
404
-                                        aBufferSize / size_t(aFrameSizeY))) {
405
+                if(!myDataRGB.initTrash(StImagePlane::ImgRGB, size_t(aFrameSizeX), size_t(aFrameSizeY))) {
406
                     signals.onError(stCString("FFmpeg: Failed allocation of RGB frame (out of memory)"));
407
                     myToRgbIsBroken = true;
408
                 } else {
409
-                    avpicture_fill((AVPicture* )myFrameRGB.Frame, myDataRGB.changeData(), stAV::PIX_FMT::RGB24,
410
-                                   aFrameSizeX, aFrameSizeY);
411
+                    ST_DEBUG_LOG(" !!! Performance warning! Using SWScaler for " + stAV::PIX_FMT::getString(aPixFmt) + " pixel format.");
412
+                    {
413
+                        StMutexAuto aLock(myMutexInfo);
414
+                        myCodecStr += StString("\n[SWScaler] Software converter (from ") + stAV::PIX_FMT::getString(aPixFmt) + stCString(" into RGB)");
415
+                    }
416
+
417
+                    myFrameRGB.Frame->data[0]     = (uint8_t* )myDataRGB.changeData();
418
+                    myFrameRGB.Frame->linesize[0] = (int      )myDataRGB.getSizeRowBytes();
419
+                    for(int aPlaneIter = 1; aPlaneIter < AV_NUM_DATA_POINTERS; ++aPlaneIter) {
420
+                        myFrameRGB.Frame->data    [aPlaneIter] = NULL;
421
+                        myFrameRGB.Frame->linesize[aPlaneIter] = 0;
422
+                    }
423
                 }
424
             }
425
         }
426
@@ -722,9 +771,12 @@
427
         StPanorama aPano = st::probePanorama(theSrcFormat,
428
                                              theStParams->Src1SizeX, theStParams->Src1SizeY,
429
                                              theStParams->Src2SizeX, theStParams->Src2SizeY);
430
-        theStParams->ViewingMode = (aPano == StPanorama_Cubemap6_1 || aPano == StPanorama_Cubemap3_2)
431
-                                 ? StViewSurface_Cubemap
432
-                                 : StViewSurface_Sphere;
433
+        theStParams->ViewingMode = StStereoParams::getViewSurfaceForPanoramaSource(aPano, true);
434
+    }
435
+    if(myIsTheaterMode && theStParams->ViewingMode == StViewSurface_Plain) {
436
+        theStParams->ViewingMode = StViewSurface_Theater;
437
+    } else if(!myIsTheaterMode && theStParams->ViewingMode == StViewSurface_Theater) {
438
+        theStParams->ViewingMode = StViewSurface_Plain;
439
     }
440
 
441
     myTextureQueue->push(theSrcDataLeft, theSrcDataRight, theStParams, theSrcFormat, theCubemapFormat, theSrcPTS);
442
@@ -737,14 +789,10 @@
443
 }
444
 
445
 void StVideoQueue::decodeLoop() {
446
-    int isFrameFinished = 0;
447
     double anAverageDelaySec = 40.0;
448
     double aPrevPts  = 0.0;
449
-    double aSlavePts = 0.0;
450
     myFramePts = 0.0;
451
-    StImage* aSlaveData = NULL;
452
     StHandle<StAVPacket> aPacket;
453
-    StImage anEmptyImg;
454
     StString aTagValue;
455
     bool isStarted = false;
456
     for(;;) {
457
@@ -780,9 +828,25 @@
458
                 myVideoClock = 0.0;
459
                 myHasDataState.reset();
460
                 isStarted = true;
461
+                aPrevPts = 0.0;
462
+                myWasFlushed = true; // force displaying the first frame
463
+                continue;
464
+            }
465
+            case StAVPacket::DATA_PACKET: {
466
+                break;
467
+            }
468
+            case StAVPacket::LAST_PACKET: {
469
+            #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
470
+                break; // redirect NULL packet to avcodec_send_packet()break;
471
+            #else
472
                 continue;
473
+            #endif
474
             }
475
             case StAVPacket::END_PACKET: {
476
+                // TODO at the end of the stream it might be needed calling
477
+                // avcodec_send_packet with NULL to initiate draining data followed by avcodec_receive_frame
478
+                // to recieve last frames.
479
+
480
                 if(!myMaster.isNull()) {
481
                     while(myHasDataState.check() && !myMaster->isInDowntime()) {
482
                         StThread::sleep(10);
483
@@ -815,233 +879,295 @@
484
             //
485
         }
486
 
487
-        // decode video frame
488
-    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
489
-        bool toTryGpu  = myUseGpu && !myIsGpuFailed;
490
-        avcodec_decode_video2(myCodecCtx, myFrame.Frame, &isFrameFinished, aPacket->getAVpkt());
491
-        bool isGpuUsed = myUseGpu && !myIsGpuFailed;
492
-        if(isGpuUsed != toTryGpu) {
493
-            if(!initCodec(myCodecAuto, isGpuUsed)) {
494
-                signals.onError(stCString("FFmpeg: Could not re-open video codec"));
495
-                deinit();
496
-                aPacket.nullify();
497
-                continue;
498
+        bool toSendPacket = true;
499
+        for(;;) {
500
+            if(!decodeFrame(aPacket, toSendPacket, isStarted, aTagValue, anAverageDelaySec, aPrevPts)) {
501
+                break;
502
             }
503
-            isFrameFinished = 0;
504
-            avcodec_decode_video2(myCodecCtx, myFrame.Frame, &isFrameFinished, aPacket->getAVpkt());
505
         }
506
-    #else
507
-        avcodec_decode_video(myCodecCtx, myFrame.Frame, &isFrameFinished,
508
-                             aPacket->getData(), aPacket->getSize());
509
-    #endif
510
-        if(isFrameFinished == 0) {
511
-            // need more packets to decode whole frame
512
-            aPacket.nullify();
513
-            continue;
514
+        aPacket.nullify();
515
+    }
516
+}
517
+
518
+bool StVideoQueue::decodeFrame(const StHandle<StAVPacket>& thePacket,
519
+                               bool& theToSendPacket,
520
+                               bool& theIsStarted,
521
+                               StString& theTagValue,
522
+                               double& theAverageDelaySec,
523
+                               double& thePrevPts) {
524
+    bool toTryMoreFrames = false;
525
+    (void )theToSendPacket;
526
+    const bool toTryGpu = myUseGpu && !myIsGpuFailed;
527
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
528
+    if(theToSendPacket) {
529
+        theToSendPacket = false;
530
+        const int aRes = avcodec_send_packet(myCodecCtx, thePacket->getType() == StAVPacket::DATA_PACKET ? thePacket->getAVpkt() : NULL);
531
+        if(aRes == AVERROR(EAGAIN)) {
532
+            // special case used by some hardware decoders - new packet cannot be sent until decoded frame is retrieved
533
+            theToSendPacket = true;
534
+        } else if(aRes < 0 && aRes != AVERROR_EOF) {
535
+            return false;
536
         }
537
+    }
538
 
539
-        if(aPacket->isKeyFrame()) {
540
-            myFramesCounter = 1;
541
+    const int aRes2 = avcodec_receive_frame(myCodecCtx, myFrame.Frame);
542
+    const bool isGpuUsed = myUseGpu && !myIsGpuFailed;
543
+    if(isGpuUsed != toTryGpu) {
544
+        if(!initCodec(myCodecAuto, isGpuUsed)) {
545
+            signals.onError(stCString("FFmpeg: Could not re-open video codec"));
546
+            deinit();
547
+            return false;
548
         }
549
+        theToSendPacket = true;
550
+        return true;
551
+    }
552
 
553
-    #ifndef ST_AV_OLDSYNC
554
-        myVideoPktPts = av_frame_get_best_effort_timestamp(myFrame.Frame);
555
-        if(myVideoPktPts == stAV::NOPTS_VALUE) {
556
-            myVideoPktPts = 0;
557
+    if(aRes2 < 0) {
558
+        // polling - if packet was not sent and new frame is not yet ready, we need to try again and again...
559
+        if(theToSendPacket) {
560
+            StThread::sleep(10);
561
+        }
562
+        return theToSendPacket;
563
+    }
564
+    toTryMoreFrames = true;
565
+#elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
566
+    int isFrameFinished = 0;
567
+    avcodec_decode_video2(myCodecCtx, myFrame.Frame, &isFrameFinished, thePacket->getAVpkt());
568
+    const bool isGpuUsed = myUseGpu && !myIsGpuFailed;
569
+    if(isGpuUsed != toTryGpu) {
570
+        if(!initCodec(myCodecAuto, isGpuUsed)) {
571
+            signals.onError(stCString("FFmpeg: Could not re-open video codec"));
572
+            deinit();
573
+            return false;
574
         }
575
+        return true;
576
+    }
577
+    if(isFrameFinished == 0) {
578
+        // need more packets to decode whole frame
579
+        return false;
580
+    }
581
+#else
582
+    int isFrameFinished = 0;
583
+    avcodec_decode_video(myCodecCtx, myFrame.Frame, &isFrameFinished,
584
+                         thePacket->getData(), thePacket->getSize());
585
+    if(isFrameFinished == 0) {
586
+        // need more packets to decode whole frame
587
+        return false;
588
+    }
589
+#endif
590
+    if(thePacket->isKeyFrame()) { // !theToSentPacket?
591
+        myFramesCounter = 1;
592
+    }
593
 
594
-        myFramePts  = double(myVideoPktPts) * av_q2d(myStream->time_base);
595
-        myFramePts -= myPtsStartBase; // normalize PTS
596
-    #else
597
-        // Save global pts to be stored in pFrame in first call
598
-        myVideoPktPts = aPacket->getPts();
599
+#ifndef ST_AV_OLDSYNC
600
+    myVideoPktPts = myFrame.getBestEffortTimestamp();
601
+    if(myVideoPktPts == stAV::NOPTS_VALUE) {
602
+        // TODO why best_effort_timestamp is invalid in case of h264_mediacodec?
603
+        myVideoPktPts = myFrame.Frame->pts;
604
+    }
605
+    if(myVideoPktPts == stAV::NOPTS_VALUE) {
606
+        myVideoPktPts = 0;
607
+    }
608
 
609
-        myFramePts = 0.0;
610
-        if(aPacket->getDts() != stAV::NOPTS_VALUE) {
611
-            myFramePts = double(aPacket->getDts());
612
-        } else {
613
-            int64_t aPktPtsSync = stAV::NOPTS_VALUE;
614
-        #ifdef ST_USE64PTR
615
-            aPktPtsSync = (int64_t )myFrame.Frame->opaque;
616
-        #else
617
-            AVFrameSideData* aSideDataSync = av_frame_get_side_data(myFrame.Frame, (AVFrameSideDataType )1000);
618
-            if(aSideDataSync != NULL) {
619
-                memcpy(&aPktPtsSync, &aSideDataSync->data, sizeof(myVideoPktPts));
620
-            }
621
-        #endif
622
-            if(aPktPtsSync != stAV::NOPTS_VALUE) {
623
-                myFramePts = double(aPktPtsSync);
624
-            }
625
-        }
626
-        myFramePts *= av_q2d(myStream->time_base);
627
-        myFramePts -= myPtsStartBase; // normalize PTS
628
+    myFramePts  = double(myVideoPktPts) * av_q2d(myStream->time_base);
629
+    myFramePts -= myPtsStartBase; // normalize PTS
630
+#else
631
+    // Save global pts to be stored in pFrame in first call
632
+    myVideoPktPts = thePacket->getPts();
633
 
634
-        syncVideo(myFrame.Frame, &myFramePts);
635
+    myFramePts = 0.0;
636
+    if(thePacket->getDts() != stAV::NOPTS_VALUE) {
637
+        myFramePts = double(thePacket->getDts());
638
+    } else {
639
+        int64_t aPktPtsSync = stAV::NOPTS_VALUE;
640
+    #ifdef ST_USE64PTR
641
+        aPktPtsSync = (int64_t )myFrame.Frame->opaque;
642
+    #else
643
+        AVFrameSideData* aSideDataSync = av_frame_get_side_data(myFrame.Frame, (AVFrameSideDataType )1000);
644
+        if(aSideDataSync != NULL) {
645
+            memcpy(&aPktPtsSync, &aSideDataSync->data, sizeof(myVideoPktPts));
646
+        }
647
     #endif
648
-
649
-        const double aDelay = myFramePts - aPrevPts;
650
-        if(aDelay > 0.0 && aDelay < 1.0) {
651
-            anAverageDelaySec = aDelay;
652
+        if(aPktPtsSync != stAV::NOPTS_VALUE) {
653
+            myFramePts = double(aPktPtsSync);
654
         }
655
-        aPrevPts = myFramePts;
656
-
657
-        // do we need to skip frames or not
658
-        static const double OVERR_LIMIT = 0.2;
659
-        static const double GREATER_LIMIT = 100.0;
660
-        if(myMaster.isNull()) {
661
-            const double anAudioClock = getAClock() + double(myAudioDelayMSec) * 0.001;
662
-            double diff = anAudioClock - myFramePts;
663
-            if(diff > OVERR_LIMIT && diff < GREATER_LIMIT) {
664
-                if(myAvDiscard != AVDISCARD_NONREF) {
665
-                    ST_DEBUG_LOG("skip frames: AVDISCARD_NONREF (on)"
666
-                        + " (aClock " + anAudioClock
667
-                        + " vClock " + myFramePts
668
-                        + " diff " + diff + ")"
669
-                    );
670
-                    myAvDiscard = AVDISCARD_NONREF;
671
-                    ///myCodecCtx->skip_frame = AVDISCARD_NONKEY;
672
-                    myCodecCtx->skip_frame = myAvDiscard;
673
-                    if(!mySlave.isNull()) {
674
-                        mySlave->myCodecCtx->skip_frame = myAvDiscard;
675
-                    }
676
+    }
677
+    myFramePts *= av_q2d(myStream->time_base);
678
+    myFramePts -= myPtsStartBase; // normalize PTS
679
+
680
+    syncVideo(myFrame.Frame, &myFramePts);
681
+#endif
682
+
683
+    const double aDelay = myFramePts - thePrevPts;
684
+    if(aDelay > 0.0 && aDelay < 1.0) {
685
+        theAverageDelaySec = aDelay;
686
+    }
687
+    thePrevPts = myFramePts;
688
+
689
+    // do we need to skip frames or not
690
+    static const double OVERR_LIMIT = 0.2;
691
+    static const double GREATER_LIMIT = 100.0;
692
+    if(myMaster.isNull()) {
693
+        const double anAudioClock = getAClock() + double(myAudioDelayMSec) * 0.001;
694
+        double diff = anAudioClock - myFramePts;
695
+        if(diff > OVERR_LIMIT && diff < GREATER_LIMIT) {
696
+            if(myAvDiscard != AVDISCARD_NONREF) {
697
+                ST_DEBUG_LOG("skip frames: AVDISCARD_NONREF (on)"
698
+                    + " (aClock " + anAudioClock
699
+                    + " vClock " + myFramePts
700
+                    + " diff " + diff + ")"
701
+                );
702
+                myAvDiscard = AVDISCARD_NONREF;
703
+                ///myCodecCtx->skip_frame = AVDISCARD_NONKEY;
704
+                myCodecCtx->skip_frame = myAvDiscard;
705
+                if(!mySlave.isNull()) {
706
+                    mySlave->myCodecCtx->skip_frame = myAvDiscard;
707
                 }
708
-            } else {
709
-                if(myAvDiscard != AVDISCARD_DEFAULT) {
710
-                    ST_DEBUG_LOG("skip frames: AVDISCARD_DEFAULT (off)");
711
-                    myAvDiscard = AVDISCARD_DEFAULT;
712
-                    myCodecCtx->skip_frame = myAvDiscard;
713
-                    if(!mySlave.isNull()) {
714
-                        mySlave->myCodecCtx->skip_frame = myAvDiscard;
715
-                    }
716
+            }
717
+        } else {
718
+            if(myAvDiscard != AVDISCARD_DEFAULT) {
719
+                ST_DEBUG_LOG("skip frames: AVDISCARD_DEFAULT (off)");
720
+                myAvDiscard = AVDISCARD_DEFAULT;
721
+                myCodecCtx->skip_frame = myAvDiscard;
722
+                if(!mySlave.isNull()) {
723
+                    mySlave->myCodecCtx->skip_frame = myAvDiscard;
724
                 }
725
             }
726
         }
727
+    }
728
 
729
-        // copy frame back from GPU to CPU memory
730
-        if(!myHWAccelCtx.isNull()) {
731
-            myHWAccelCtx->retrieveFrame(*this, myFrame.Frame);
732
-        }
733
+    // copy frame back from GPU to CPU memory
734
+    if(!myHWAccelCtx.isNull()) {
735
+        myHWAccelCtx->retrieveFrame(*this, myFrame.Frame);
736
+    }
737
 
738
-        // we currently allow to override source format stored in metadata
739
-    #ifdef ST_AV_NEWSTEREO
740
-        if(AVFrameSideData* aSideDataS3d = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_STEREO3D)) {
741
-            AVStereo3D* aStereo = (AVStereo3D* )aSideDataS3d->data;
742
-            myStFormatInStream = stAV::stereo3dAvToSt(aStereo->type);
743
-            if(aStereo->flags & AV_STEREO3D_FLAG_INVERT) {
744
-                myStFormatInStream = st::formatReversed(myStFormatInStream);
745
-            }
746
+    // we currently allow to override source format stored in metadata
747
+#ifdef ST_AV_NEWSTEREO
748
+    if(AVFrameSideData* aSideDataS3d = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_STEREO3D)) {
749
+        AVStereo3D* aStereo = (AVStereo3D* )aSideDataS3d->data;
750
+        myStFormatInStream = stAV::stereo3dAvToSt(aStereo->type);
751
+        if(aStereo->flags & AV_STEREO3D_FLAG_INVERT) {
752
+            myStFormatInStream = st::formatReversed(myStFormatInStream);
753
         }
754
-    #endif
755
-    #if(LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
756
-        if(const AVFrameSideData* aSideDataRot = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_DISPLAYMATRIX)) {
757
-            if(aSideDataRot->size >= int(9 * sizeof(int32_t))) {
758
-                const double aRotDeg = -av_display_rotation_get((const int32_t* )aSideDataRot->data);
759
-                if(!st::isNaN(aRotDeg)) {
760
-                    myRotateDeg = -int(aRotDeg - 360 * std::floor(aRotDeg / 360 + 0.9 / 360));
761
-                }
762
+    }
763
+#endif
764
+#if(LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
765
+    if(const AVFrameSideData* aSideDataRot = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_DISPLAYMATRIX)) {
766
+        if(aSideDataRot->size >= int(9 * sizeof(int32_t))) {
767
+            const double aRotDeg = -av_display_rotation_get((const int32_t* )aSideDataRot->data);
768
+            if(!st::isNaN(aRotDeg)) {
769
+                myRotateDeg = -int(aRotDeg - 360 * std::floor(aRotDeg / 360 + 0.9 / 360));
770
             }
771
         }
772
-    #endif
773
-        if(stAV::meta::readTag(myFrame.Frame, THE_SRC_MODE_KEY, aTagValue)) {
774
-            for(size_t aSrcId = 0;; ++aSrcId) {
775
-                const StFFmpegStereoFormat& aFlag = STEREOFLAGS[aSrcId];
776
-                if(aFlag.stID == StFormat_AUTO || aFlag.name == NULL) {
777
-                    break;
778
-                } else if(aTagValue == aFlag.name) {
779
-                    myStFormatInStream = aFlag.stID;
780
-                    //ST_DEBUG_LOG("  read srcFormat from tags= " + myStFormatInStream);
781
-                    break;
782
-                }
783
+    }
784
+#endif
785
+    if(stAV::meta::readTag(myFrame.Frame, THE_SRC_MODE_KEY, theTagValue)) {
786
+        for(size_t aSrcId = 0;; ++aSrcId) {
787
+            const StFFmpegStereoFormat& aFlag = STEREOFLAGS[aSrcId];
788
+            if(aFlag.stID == StFormat_AUTO || aFlag.name == NULL) {
789
+                break;
790
+            } else if(theTagValue == aFlag.name) {
791
+                myStFormatInStream = aFlag.stID;
792
+                //ST_DEBUG_LOG("  read srcFormat from tags= " + myStFormatInStream);
793
+                break;
794
             }
795
         }
796
-        // override source format stored in metadata
797
-        StFormat  aSrcFormat     = myStFormatByUser;
798
-        StCubemap aCubemapFormat = aPacket->getSource()->ViewingMode == StViewSurface_Cubemap ? StCubemap_Packed : StCubemap_OFF;
799
-        if(aSrcFormat == StFormat_AUTO) {
800
-            // prefer info stored in the stream itself
801
-            aSrcFormat = myStFormatInStream;
802
-        }
803
-        if(aSrcFormat == StFormat_AUTO) {
804
-            // try using format detected from file name
805
-            aSrcFormat = myStFormatByName;
806
-        }
807
-        /*if(aSrcFormat == StFormat_AUTO
808
-        && sizeY() != 0) {
809
-            // try detection based on aspect ratio
810
-            aSrcFormat = st::formatFromRatio(GLfloat(sizeX()) / GLfloat(sizeY()));
811
-        }*/
812
-
813
-        prepareFrame(aSrcFormat);
814
+    }
815
+    // override source format stored in metadata
816
+    StFormat  aSrcFormat     = myStFormatByUser;
817
+    StCubemap aCubemapFormat = StCubemap_OFF;
818
+    if(thePacket->getSource()->ViewingMode == StViewSurface_Cubemap) {
819
+        aCubemapFormat = StCubemap_Packed;
820
+    } else if(thePacket->getSource()->ViewingMode == StViewSurface_CubemapEAC) {
821
+        aCubemapFormat = StCubemap_PackedEAC;
822
+    }
823
 
824
-        if(!mySlave.isNull()) {
825
-            if(isStarted) {
826
-                StHandle<StStereoParams> aParams = aPacket->getSource();
827
-                if(!aParams.isNull()) {
828
-                    aParams->setSeparationNeutral(myHParallax);
829
-                    aParams->setZRotateZero((float )myRotateDeg);
830
-                }
831
-                isStarted = false;
832
+    if(aSrcFormat == StFormat_AUTO) {
833
+        // prefer info stored in the stream itself
834
+        aSrcFormat = myStFormatInStream;
835
+    }
836
+    if(aSrcFormat == StFormat_AUTO) {
837
+        // try using format detected from file name
838
+        aSrcFormat = myStFormatByName;
839
+    }
840
+    /*if(aSrcFormat == StFormat_AUTO
841
+    && sizeY() != 0) {
842
+        // try detection based on aspect ratio
843
+        aSrcFormat = st::formatFromRatio(GLfloat(sizeX()) / GLfloat(sizeY()));
844
+    }*/
845
+
846
+    prepareFrame(aSrcFormat);
847
+
848
+    if(!mySlave.isNull()) {
849
+        if(theIsStarted) {
850
+            StHandle<StStereoParams> aParams = thePacket->getSource();
851
+            if(!aParams.isNull()) {
852
+                aParams->setSeparationNeutral(myHParallax);
853
+                aParams->setZRotateZero((float )myRotateDeg);
854
             }
855
+            theIsStarted = false;
856
+        }
857
 
858
-            for(;;) {
859
-                // wait data from Slave
860
-                if(aSlaveData == NULL) {
861
-                    aSlaveData = mySlave->waitData(aSlavePts);
862
-                }
863
-                if(aSlaveData != NULL) {
864
-                    const double aPtsDiff = myFramePts - aSlavePts;
865
-                    if(aPtsDiff > 0.5 * anAverageDelaySec) {
866
-                        // wait for more recent frame from slave thread
867
+        StImage* aSlaveData = NULL;
868
+        double aSlavePts = 0.0;
869
+        for(;;) {
870
+            // wait data from Slave
871
+            if(aSlaveData == NULL) {
872
+                aSlaveData = mySlave->waitData(aSlavePts);
873
+            }
874
+            if(aSlaveData != NULL) {
875
+                const double aPtsDiff = myFramePts - aSlavePts;
876
+                if(aPtsDiff > 0.5 * theAverageDelaySec) {
877
+                    // wait for more recent frame from slave thread
878
+                    mySlave->unlockData();
879
+                    aSlaveData = NULL;
880
+                    StThread::sleep(10);
881
+                    continue;
882
+                } else if(aPtsDiff < -0.5 * theAverageDelaySec) {
883
+                    // too far...
884
+                    if(aPtsDiff < -6.0) {
885
+                        // result of seeking?
886
                         mySlave->unlockData();
887
                         aSlaveData = NULL;
888
-                        StThread::sleep(10);
889
-                        continue;
890
-                    } else if(aPtsDiff < -0.5 * anAverageDelaySec) {
891
-                        // too far...
892
-                        if(aPtsDiff < -6.0) {
893
-                            // result of seeking?
894
-                            mySlave->unlockData();
895
-                            aSlaveData = NULL;
896
-                        }
897
-                        break;
898
                     }
899
+                    break;
900
+                }
901
 
902
-                    pushFrame(myDataAdp, *aSlaveData, aPacket->getSource(), StFormat_SeparateFrames, aCubemapFormat, myFramePts);
903
+                pushFrame(myDataAdp, *aSlaveData, thePacket->getSource(), StFormat_SeparateFrames, aCubemapFormat, myFramePts);
904
 
905
-                    aSlaveData = NULL;
906
-                    mySlave->unlockData();
907
-                } else {
908
-                    pushFrame(myDataAdp, anEmptyImg, aPacket->getSource(), aSrcFormat, aCubemapFormat, myFramePts);
909
-                }
910
-                break;
911
+                aSlaveData = NULL;
912
+                mySlave->unlockData();
913
+            } else {
914
+                pushFrame(myDataAdp, myEmptyImage, thePacket->getSource(), aSrcFormat, aCubemapFormat, myFramePts);
915
             }
916
-        } else if(!myMaster.isNull()) {
917
-            // push data to Master
918
-            myHasDataState.set();
919
-        } else {
920
-            if(isStarted) {
921
-                StHandle<StStereoParams> aParams = aPacket->getSource();
922
-                if(!aParams.isNull()) {
923
-                    aParams->setSeparationNeutral(myHParallax);
924
-                    aParams->setZRotateZero((float )myRotateDeg);
925
-                }
926
-                isStarted = false;
927
+            break;
928
+        }
929
+    } else if(!myMaster.isNull()) {
930
+        // push data to Master
931
+        myHasDataState.set();
932
+    } else {
933
+        if(theIsStarted) {
934
+            StHandle<StStereoParams> aParams = thePacket->getSource();
935
+            if(!aParams.isNull()) {
936
+                aParams->setSeparationNeutral(myHParallax);
937
+                aParams->setZRotateZero((float )myRotateDeg);
938
             }
939
+            theIsStarted = false;
940
+        }
941
 
942
-            // simple one-stream case
943
-            if(aSrcFormat == StFormat_FrameSequence) {
944
-                if(isOddNumber(myFramesCounter)) {
945
-                    myCachedFrame.fill(myDataAdp, false);
946
-                } else {
947
-                    pushFrame(myCachedFrame, myDataAdp, aPacket->getSource(), StFormat_FrameSequence, aCubemapFormat, myFramePts);
948
-                }
949
-                ++myFramesCounter;
950
+        // simple one-stream case
951
+        if(aSrcFormat == StFormat_FrameSequence) {
952
+            if(isOddNumber(myFramesCounter)) {
953
+                myCachedFrame.fill(myDataAdp, false);
954
             } else {
955
-                pushFrame(myDataAdp, anEmptyImg, aPacket->getSource(), aSrcFormat, aCubemapFormat, myFramePts);
956
+                pushFrame(myCachedFrame, myDataAdp, thePacket->getSource(), StFormat_FrameSequence, aCubemapFormat, myFramePts);
957
             }
958
+            ++myFramesCounter;
959
+        } else {
960
+            pushFrame(myDataAdp, myEmptyImage, thePacket->getSource(), aSrcFormat, aCubemapFormat, myFramePts);
961
         }
962
-
963
-        myFrame.reset();
964
-        aPacket.nullify(); // and now packet finished
965
     }
966
+
967
+    myFrame.reset();
968
+    return toTryMoreFrames;
969
 }
970
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideoQueue.h -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideoQueue.h Changed
104
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * StMoviePlayer program is free software: you can redistribute it and/or modify
7
  * it under the terms of the GNU General Public License as published by
8
@@ -59,7 +59,7 @@
9
     /**
10
      * Release decoder.
11
      */
12
-    virtual void decoderDestroy() = 0;
13
+    virtual void decoderDestroy(AVCodecContext* theCodecCtx) = 0;
14
 
15
     /**
16
      * AVFrame initialization callback.
17
@@ -198,17 +198,34 @@
18
     }
19
 
20
     /**
21
+     * Set theater mode.
22
+     */
23
+    ST_LOCAL void setTheaterMode(bool theIsTheater) {
24
+        myIsTheaterMode = theIsTheater;
25
+    }
26
+
27
+    /**
28
      * Stick to panorama 360 mode.
29
      */
30
     ST_LOCAL void setStickPano360(bool theToStick) {
31
         myToStickPano360 = theToStick;
32
     }
33
 
34
+    /**
35
+     * Set if JPS file should be read as Left/Right (TRUE) of as Right/Left (FALSE).
36
+     */
37
+    ST_LOCAL void setSwapJPS(bool theToSwap) { myToSwapJps = theToSwap; }
38
+
39
     ST_LOCAL StVideoQueue(const StHandle<StGLTextureQueue>& theTextureQueue,
40
                           const StHandle<StVideoQueue>&     theMaster = StHandle<StVideoQueue>());
41
     ST_LOCAL virtual ~StVideoQueue();
42
 
43
     /**
44
+     * Return codec type.
45
+     */
46
+    ST_LOCAL virtual AVMediaType getCodecType() const ST_ATTR_OVERRIDE { return AVMEDIA_TYPE_VIDEO; }
47
+
48
+    /**
49
      * Initialization function.
50
      * @param theFormatCtx pointer to video format context
51
      * @param theStreamId  stream id in video format context
52
@@ -342,6 +359,22 @@
53
 private:
54
 
55
     /**
56
+     * Detect 720in1080 streams with cropping information
57
+     */
58
+    ST_LOCAL bool check720in1080() const {
59
+        return (sizeX() == 1280) && (sizeY() == 720)
60
+            && (getCodedSizeX() == 1920)
61
+            && (getCodedSizeY() == 1080 || getCodedSizeY() == 1088);
62
+    }
63
+
64
+    ST_LOCAL bool decodeFrame(const StHandle<StAVPacket>& thePacket,
65
+                              bool& theToSendPacket,
66
+                              bool& theIsStarted,
67
+                              StString& theTagValue,
68
+                              double& theAverageDelaySec,
69
+                              double& thePrevPts);
70
+
71
+    /**
72
      * Initialize adapter over AVframe or perform to RGB conversion.
73
      */
74
     ST_LOCAL void prepareFrame(const StFormat theSrcFormat);
75
@@ -364,8 +397,10 @@
76
     StHandle<StVideoQueue>     mySlave;           //!< handle to Slave  decoding thread
77
 
78
     StHandle<StHWAccelContext> myHWAccelCtx;
79
-#if defined(__APPLE__) || defined(__ANDROID__)
80
-    AVCodec*                   myCodecH264HW;     //!< h264 decoder using dedicated hardware (VDA codec on OS X; Android Media Codec)
81
+#if defined(__ANDROID__)
82
+    AVCodec*                   myCodecH264HW;     //!< h264 decoder using dedicated hardware (Android Media Codec)
83
+    AVCodec*                   myCodecHevcHW;     //!< hevc decoder using dedicated hardware
84
+    AVCodec*                   myCodecVp9HW;      //!< vp9  decoder using dedicated hardware
85
 #endif
86
     AVCodec*                   myCodecOpenJpeg;   //!< libopenjpeg decoder
87
     bool                       myUseGpu;          //!< activate decoding on GPU when possible
88
@@ -398,12 +433,15 @@
89
 
90
     int64_t                    myFramesCounter;
91
     StImage                    myCachedFrame;
92
+    StImage                    myEmptyImage;
93
     bool                       myWasFlushed;
94
 
95
     volatile StFormat          myStFormatByUser;  //!< source format specified by user
96
     volatile StFormat          myStFormatByName;  //!< source format detected from file name
97
     volatile StFormat          myStFormatInStream;//!< source format information retrieved from stream
98
+    volatile bool              myIsTheaterMode;   //!< flag indicating theater mode
99
     volatile bool              myToStickPano360;  //!< stick to panorama 360 mode
100
+    volatile bool              myToSwapJps;       //!< read JPS as Left/Right instead of Right/Left
101
 
102
 };
103
 
104
sview-17_04.tar.gz/StMoviePlayer/StVideo/StVideoTimer.cpp -> sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideoTimer.cpp Changed
12
 
1
@@ -139,8 +139,8 @@
2
                 if(mySpeedSlow * myDelayTimer > myDelayVVAver) {
3
                     myDelayTimer = mySpeedSlowRev * myDelayVVAver;
4
                 } else if(mySpeedFastSkip * myDelayTimer < myDelayVVAver) {
5
-                    //myVideo->getTextureQueue()->drop(2);
6
-                    myVideo->getTextureQueue()->drop(1);
7
+                    //myVideo->getTextureQueue()->drop(2, myVideoPtsNextSec);
8
+                    myVideo->getTextureQueue()->drop(1, myVideoPtsNextSec);
9
                     myDelayTimer = mySpeedFastRev * myDelayVVAver;
10
                 } else if(mySpeedFast * myDelayTimer < myDelayVVAver) {
11
                     myDelayTimer = mySpeedFastRev * myDelayVVAver;
12
sview-20_08.tar.gz/StMoviePlayer/StVideo/StVideoToolbox.cpp Added
250
 
1
@@ -0,0 +1,248 @@
2
+/**
3
+ * Copyright © 2020 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * StMoviePlayer program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * StMoviePlayer program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ * See the GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public
16
+ * License along with this program.
17
+ * If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include "StVideoQueue.h"
21
+
22
+#if defined(__APPLE__)
23
+
24
+#include <StAV/StAVPacket.h>
25
+#include <StAV/StAVFrame.h>
26
+#include <StAV/StAVBufferPool.h>
27
+#include <StLibrary.h>
28
+
29
+#include <vector>
30
+
31
+#include <CoreServices/CoreServices.h>
32
+
33
+extern "C" {
34
+  #include <libavcodec/videotoolbox.h>
35
+  #include <libavutil/buffer.h>
36
+  #include <libavutil/imgutils.h>
37
+};
38
+
39
+/**
40
+ * VideoToolbox HWAccel context.
41
+ */
42
+class StVideoToolboxContext : public StHWAccelContext {
43
+
44
+        public:
45
+
46
+    /**
47
+     * Empty constructor.
48
+     */
49
+    StVideoToolboxContext()
50
+    : myFrameTmp(NULL),
51
+      myHasDevice(false){
52
+        //
53
+    }
54
+
55
+    /**
56
+     * Destructor.
57
+     */
58
+    virtual ~StVideoToolboxContext() {
59
+        release();
60
+    }
61
+
62
+    /**
63
+     * Release context.
64
+     */
65
+    void release();
66
+
67
+    /**
68
+     * Return true if VideoToolbox has been successfully initialized.
69
+     */
70
+    virtual bool isValid() const ST_ATTR_OVERRIDE { return myHasDevice; }
71
+
72
+    /**
73
+     * Create context.
74
+     */
75
+    virtual bool create(StVideoQueue& theVideo) ST_ATTR_OVERRIDE;
76
+
77
+    /**
78
+     * Destroy decoder.
79
+     */
80
+    virtual void decoderDestroy(AVCodecContext* theCodecCtx) ST_ATTR_OVERRIDE {
81
+        myPoolsTmp[0].release();
82
+        myPoolsTmp[1].release();
83
+        myPoolsTmp[2].release();
84
+        myPoolsTmp[3].release();
85
+        if(theCodecCtx != NULL && myHasDevice) {
86
+            av_videotoolbox_default_free(theCodecCtx);
87
+        }
88
+        myHasDevice = false;
89
+    }
90
+
91
+    /**
92
+     * Create decoder.
93
+     */
94
+    virtual bool decoderCreate(StVideoQueue&   theVideo,
95
+                               AVCodecContext* theCodecCtx) ST_ATTR_OVERRIDE {
96
+        const StSignal<void (const StCString& )>& onError = theVideo.signals.onError;
97
+        decoderDestroy(theCodecCtx);
98
+
99
+        const int anAvErr = av_videotoolbox_default_init(theCodecCtx);
100
+        if(anAvErr < 0) {
101
+            onError(stCString("StVideoQueue: Error creating Videotoolbox decoder"));
102
+            return false;
103
+        }
104
+        myHasDevice = true;
105
+        return true;
106
+    }
107
+
108
+    /**
109
+     * AVFrame initialization callback.
110
+     */
111
+    virtual int getFrameBuffer(StVideoQueue& ,
112
+                               AVFrame* ) ST_ATTR_OVERRIDE {
113
+        return -1; // method is unused
114
+    }
115
+
116
+    /**
117
+     * Fetch decoded results into specified frame.
118
+     */
119
+    virtual bool retrieveFrame(StVideoQueue& theVideo,
120
+                               AVFrame* theFrame) ST_ATTR_OVERRIDE;
121
+
122
+        private:
123
+
124
+    StAVBufferPool myPoolsTmp[4];
125
+    AVFrame*       myFrameTmp;
126
+    bool           myHasDevice;
127
+
128
+};
129
+
130
+void StVideoToolboxContext::release() {
131
+    decoderDestroy(NULL);
132
+    av_frame_free(&myFrameTmp);
133
+}
134
+
135
+bool StVideoToolboxContext::create(StVideoQueue& ) {
136
+    myFrameTmp = av_frame_alloc();
137
+    if(myFrameTmp == NULL) {
138
+        release();
139
+        return false;
140
+    }
141
+    return true;
142
+}
143
+
144
+bool StVideoToolboxContext::retrieveFrame(StVideoQueue& ,
145
+                                          AVFrame* theFrame) {
146
+    if(!isValid()
147
+     || theFrame->format != stAV::PIX_FMT::VIDEOTOOLBOX_VLD) {
148
+        return false;
149
+    }
150
+
151
+    av_frame_unref(myFrameTmp);
152
+
153
+    CVPixelBufferRef aPixBuf = (CVPixelBufferRef )theFrame->data[3];
154
+    const OSType aPixBufFormat = CVPixelBufferGetPixelFormatType(aPixBuf);
155
+    switch(aPixBufFormat) {
156
+        case kCVPixelFormatType_420YpCbCr8Planar: myFrameTmp->format = AV_PIX_FMT_YUV420P; break;
157
+        case kCVPixelFormatType_422YpCbCr8:       myFrameTmp->format = AV_PIX_FMT_UYVY422; break;
158
+        case kCVPixelFormatType_32BGRA:           myFrameTmp->format = AV_PIX_FMT_BGRA; break;
159
+        case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
160
+        case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: myFrameTmp->format = AV_PIX_FMT_NV12; break;
161
+        case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
162
+        case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: myFrameTmp->format = AV_PIX_FMT_P010; break;
163
+        default: {
164
+            ST_ERROR_LOG("StVideoToolboxContext: unsupported pixel format " + int(aPixBufFormat));
165
+            return false;
166
+        }
167
+    }
168
+
169
+    CVReturn err = CVPixelBufferLockBaseAddress(aPixBuf, kCVPixelBufferLock_ReadOnly);
170
+    if(err != kCVReturnSuccess) {
171
+        ST_ERROR_LOG("StVideoToolboxContext: Error locking the pixel buffer");
172
+        return false;
173
+    }
174
+
175
+    myFrameTmp->width  = theFrame->width;
176
+    myFrameTmp->height = theFrame->height;
177
+    size_t aDataSize[4] = { 0 };
178
+
179
+    uint8_t*   aData[4] = { 0 };
180
+    int    aLineSize[4] = { 0 };
181
+    const int aNbPlanes = CVPixelBufferIsPlanar(aPixBuf) ? CVPixelBufferGetPlaneCount(aPixBuf) : 1;
182
+    if(CVPixelBufferIsPlanar(aPixBuf)) {
183
+        for(int aPlaneIter = 0; aPlaneIter < aNbPlanes; ++aPlaneIter) {
184
+            aData[aPlaneIter] = (uint8_t* )CVPixelBufferGetBaseAddressOfPlane(aPixBuf, aPlaneIter);
185
+            aLineSize[aPlaneIter] = CVPixelBufferGetBytesPerRowOfPlane(aPixBuf, aPlaneIter);
186
+
187
+            const int aTmpStride = aLineSize[aPlaneIter]; //(int )getAligned(CVPixelBufferGetWidthOfPlane(aPixBuf, aPlaneIter) * bytesPerPixel, 32);
188
+            myFrameTmp->linesize[aPlaneIter] = aTmpStride;
189
+            aDataSize[aPlaneIter] = size_t(aTmpStride) * size_t(CVPixelBufferGetHeightOfPlane(aPixBuf, aPlaneIter));
190
+        }
191
+    } else {
192
+        aData[0] = (uint8_t* )CVPixelBufferGetBaseAddress(aPixBuf);
193
+        aLineSize[0] = CVPixelBufferGetBytesPerRow(aPixBuf);
194
+
195
+        const int aTmpStride = aLineSize[0]; //(int )getAligned(CVPixelBufferGetWidth(aPixBuf) * bytesPerPixel, 32);
196
+        myFrameTmp->linesize[0] = aTmpStride;
197
+        aDataSize[0] = size_t(aTmpStride) * size_t(CVPixelBufferGetHeight(aPixBuf));
198
+    }
199
+
200
+    for(int aPlaneIter = 0; aPlaneIter < aNbPlanes; ++aPlaneIter) {
201
+        myFrameTmp->buf[aPlaneIter] = myPoolsTmp[aPlaneIter].init(aDataSize[aPlaneIter]) ? myPoolsTmp[aPlaneIter].getBuffer() : NULL;
202
+        if(myFrameTmp->buf[aPlaneIter] == NULL) {
203
+            ST_ERROR_LOG("StVideoToolboxContext: unable to allocate frame buffers");
204
+            av_frame_unref(myFrameTmp);
205
+            CVPixelBufferUnlockBaseAddress(aPixBuf, kCVPixelBufferLock_ReadOnly);
206
+            return false;
207
+        }
208
+        myFrameTmp->data[aPlaneIter] = myFrameTmp->buf[aPlaneIter]->data;
209
+    }
210
+    //int anAvErrBuf = av_frame_get_buffer(myFrameTmp, 0);
211
+    //if(anAvErrBuf < 0) { return false; }
212
+
213
+    av_image_copy(myFrameTmp->data, myFrameTmp->linesize,
214
+                  (const uint8_t** )aData, aLineSize, (AVPixelFormat )myFrameTmp->format,
215
+                  theFrame->width, theFrame->height);
216
+
217
+    const int anAvErr = av_frame_copy_props(myFrameTmp, theFrame);
218
+    CVPixelBufferUnlockBaseAddress(aPixBuf, kCVPixelBufferLock_ReadOnly);
219
+    if(anAvErr < 0) {
220
+        ST_ERROR_LOG("StVideoToolboxContext: Error copying frame properties");
221
+        av_frame_unref(myFrameTmp);
222
+        return false;
223
+    }
224
+
225
+    av_frame_unref   (theFrame);
226
+    av_frame_move_ref(theFrame, myFrameTmp);
227
+    return true;
228
+}
229
+
230
+bool StVideoQueue::hwaccelInit() {
231
+    if(myCodecCtx->codec_id == AV_CODEC_ID_NONE) {
232
+        return false;
233
+    }
234
+
235
+    if(myHWAccelCtx.isNull()) {
236
+        myHWAccelCtx = new StVideoToolboxContext();
237
+        if(!myHWAccelCtx->create(*this)) {
238
+            return false;
239
+        }
240
+    }
241
+
242
+    if(!myHWAccelCtx->decoderCreate(*this, myCodecCtx)) {
243
+        return false;
244
+    }
245
+    fillCodecInfo(myCodecCtx->codec, " (VideoToolbox)");
246
+    return true;
247
+}
248
+
249
+#endif // __APPLE__
250
sview-17_04.tar.gz/StMoviePlayer/lang/chinese/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/chinese/StMoviePlayer.lng Changed
57
 
1
@@ -62,6 +62,7 @@
2
 1260=接近
3
 1261=线性
4
 1262=混纺交织
5
+?1263=Trilinear
6
 1270=重置默认
7
 1271=亮度
8
 1272=饱和度
9
@@ -70,10 +71,13 @@
10
 1281=球面
11
 1282=圆筒
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1287=Orient audio
17
 ?1288=Stick at panorama 360°
18
+?1293=Equiangular cubemap
19
+?1294=Theater
20
 1300=音频
21
 1301=无
22
 1302=音/视频 延迟
23
@@ -93,9 +97,11 @@
24
 ?1359=Bottom
25
 ?1360=Plain text
26
 ?1361=Lite HTML
27
+?1370=Apply stereo format
28
 1400=改变设备
29
 1401=关于插件…
30
 1402=FPS控制
31
+?1404=Exclusive Fullscreen mode
32
 1420=同时
33
 1421=显示表
34
 1422=减少CPU的使用
35
@@ -131,6 +137,7 @@
36
 ?1705=On one click windowed mode
37
 ?1710=Hide system navigation bar
38
 ?1711=Open last played file on startup
39
+?1712=Swap JPS/PNS views order
40
 2000=选择视频文件打开
41
 2001=选择左视频文件打开
42
 2002=选择右视频文件打开
43
@@ -139,6 +146,8 @@
44
 2005=文件删除
45
 2006=确定完全移除吗?
46
 2007=激活解码器:
47
+?2008=Choose audio file to attach
48
+?2009=Choose subtitles file to attach
49
 2010=选择保存快照位置
50
 2011=什么也没有保存!
51
 2012=快照不为空!
52
@@ -253,3 +262,4 @@
53
 ?6055=X Rotation - up
54
 ?6056=X Rotation - down
55
 ?6057=Enable/disable panorama mode
56
+?6058=Show/hide GUI
57
sview-17_04.tar.gz/StMoviePlayer/lang/czech/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/czech/StMoviePlayer.lng Changed
57
 
1
@@ -63,6 +63,7 @@
2
 1260=Nevyhlazovat
3
 1261=Lineární
4
 1262=Odstranit prokládání
5
+?1263=Trilinear
6
 1270=Resetovat nastavení
7
 1271=Jas
8
 1272=Sytost
9
@@ -71,10 +72,13 @@
10
 1281=Koule
11
 1282=Válec
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1287=Orient audio
17
 ?1288=Stick at panorama 360°
18
+?1293=Equiangular cubemap
19
+?1294=Theater
20
 1300=Zvuk
21
 1301=Vypnout zvuk
22
 1302=Zpoždění zvuku
23
@@ -94,9 +98,11 @@
24
 ?1359=Bottom
25
 1360=Plain text
26
 1361=Lite HTML
27
+?1370=Apply stereo format
28
 1400=Vybrat zařízení
29
 1401=O modulu…
30
 1402=FPS nastavení
31
+?1404=Exclusive Fullscreen mode
32
 1420=Vertikální synchronizace
33
 1421=Zobrazovat snímkování (fps)
34
 1422=Omezit využití CPU
35
@@ -132,6 +138,7 @@
36
 ?1705=On one click windowed mode
37
 ?1710=Hide system navigation bar
38
 ?1711=Open last played file on startup
39
+?1712=Swap JPS/PNS views order
40
 2000=Otevřít video
41
 2001=Otevřít video s LEVOU stopou
42
 2002=Otevřít video s PRAVOU stopou
43
@@ -140,6 +147,8 @@
44
 2005=Vymazat soubor
45
 2006=Skutečně chcete hodit soubor do koše?
46
 2007=Aktivní dekódery
47
+?2008=Choose audio file to attach
48
+?2009=Choose subtitles file to attach
49
 2010=Zvolte místo pro uložení obrázku
50
 2011=Nic není otevřeno!
51
 2012=Obraz není možné uložit!
52
@@ -254,3 +263,4 @@
53
 ?6055=X Rotation - up
54
 ?6056=X Rotation - down
55
 ?6057=Enable/disable panorama mode
56
+?6058=Show/hide GUI
57
sview-17_04.tar.gz/StMoviePlayer/lang/english/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/english/StMoviePlayer.lng Changed
57
 
1
@@ -62,6 +62,7 @@
2
 1260=Nearest
3
 1261=Linear
4
 1262=Blend Deinterlace
5
+?1263=Trilinear
6
 1270=Reset to defaults
7
 1271=Brightness
8
 1272=Saturation
9
@@ -70,10 +71,13 @@
10
 1281=Sphere
11
 1282=Cylinder
12
 1283=Cubemap
13
+1284=Hemisphere
14
 1285=Track orientation
15
 1286=Track orientation (poor)
16
 1287=Orient audio
17
 1288=Stick at panorama 360°
18
+1293=Equiangular cubemap
19
+1294=Theater
20
 1300=Audio
21
 1301=None
22
 1302=Audio/Video delay
23
@@ -93,9 +97,11 @@
24
 1359=Bottom
25
 1360=Plain text
26
 1361=Lite HTML
27
+1370=Apply stereo format
28
 1400=Change device
29
 1401=About Plugin...
30
 1402=FPS Control
31
+1404=Exclusive Fullscreen mode
32
 1420=VSync
33
 1421=Show Meter
34
 1422=Reduce CPU usage
35
@@ -131,6 +137,7 @@
36
 1705=On one click in windowed mode
37
 1710=Hide system navigation bar
38
 1711=Open last played file on startup
39
+1712=Swap JPS/PNS views order
40
 2000=Choose the video file to open
41
 2001=Choose LEFT video file to open
42
 2002=Choose RIGHT video file to open
43
@@ -139,6 +146,8 @@
44
 2005=File deletion
45
 2006=Do you really want to completely remove this file?
46
 2007=Active decoders:
47
+2008=Choose audio file to attach
48
+2009=Choose subtitles file to attach
49
 2010=Choose location to save snapshot
50
 2011=Nothing to save!
51
 2012=Snapshot not available!
52
@@ -253,3 +262,4 @@
53
 6055=X Rotation - up
54
 6056=X Rotation - down
55
 6057=Enable/disable panorama mode
56
+6058=Show/hide GUI
57
sview-17_04.tar.gz/StMoviePlayer/lang/french/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/french/StMoviePlayer.lng Changed
57
 
1
@@ -62,6 +62,7 @@
2
 1260=Plus proche
3
 1261=Lineaire
4
 1262=Blend Deinterlace
5
+1263=Trilinéaire
6
 1270=Rétablir par défaut
7
 1271=Brightness
8
 1272=Saturation
9
@@ -70,10 +71,13 @@
10
 1281=Sphère
11
 1282=Cylindre
12
 1283=Cubemap
13
+1284=Hémisphère
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1287=Orient audio
17
 ?1288=Stick at panorama 360°
18
+?1293=Equiangular cubemap
19
+1294=Théâtre
20
 1300=Audio
21
 1301=Aucun
22
 1302=Audio/Video delay
23
@@ -93,9 +97,11 @@
24
 1359=Au fond
25
 ?1360=Plain text
26
 ?1361=Lite HTML
27
+?1370=Apply stereo format
28
 1400=Changer la sortie
29
 1401=A propos du Plugin...
30
 1402=Contrôle de I/S
31
+?1404=Exclusive Fullscreen mode
32
 1420=Synchro Vert.
33
 1421=Voir I/S
34
 1422=Réduire l'utilisation de CPU
35
@@ -131,6 +137,7 @@
36
 ?1705=On one click windowed mode
37
 ?1710=Hide system navigation bar
38
 ?1711=Open last played file on startup
39
+1712=JPS/PNS échange de vues pour
40
 2000=Choix du fichier vidéo à ouvrir
41
 2001=Choix du fichier vidéo Gauche à ouvrir
42
 2002=Choix du fichier vidéo Droite à ouvrir
43
@@ -139,6 +146,8 @@
44
 ?2005=File deletion
45
 ?2006=Do you really want to completely remove this file?
46
 ?2007=Active decoders:
47
+2008=Choix du fichier audio à joindre
48
+2009=Choix du fichier sous-titres à joindre
49
 2010=Emplacement de la capture écran
50
 2011=Rien à enregistrer!
51
 2012=Capture non disponible!
52
@@ -253,3 +262,4 @@
53
 ?6055=X Rotation - up
54
 ?6056=X Rotation - down
55
 6057=Activer / désactiver le mode panorama
56
+6058=Masquer l'interface
57
sview-17_04.tar.gz/StMoviePlayer/lang/german/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/german/StMoviePlayer.lng Changed
57
 
1
@@ -62,6 +62,7 @@
2
 1260=Nearest
3
 1261=Linear
4
 1262=Blend Deinterlace
5
+1263=Trilinear
6
 1270=Auf Standardwerte zurücksetzen
7
 1271=Helligkeit
8
 1272=Sättigung
9
@@ -70,10 +71,13 @@
10
 1281=Kugel
11
 1282=Zylinder
12
 1283=Cubemap
13
+1284=Hemisphäre
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1287=Orient audio
17
 ?1288=Stick at panorama 360°
18
+?1293=Equiangular cubemap
19
+1294=Theater
20
 1300=Audio
21
 1301=keiner
22
 1302=Audio/Video Verzögerung
23
@@ -93,9 +97,11 @@
24
 1359=Boden
25
 1360=Plain text
26
 1361=Lite HTML
27
+1370=Stereoformat anwenden
28
 1400=Gerät ändern
29
 1401=Über Plugin...
30
 1402=FPS Kontrolle
31
+1404=Exklusiver Vollbildmodus
32
 1420=VSync
33
 1421=Zeige Meter
34
 1422=Reduce CPU usage
35
@@ -131,6 +137,7 @@
36
 ?1705=Only when windowed
37
 1710=Navigationsleiste ausblenden
38
 ?1711=Open last played file on startup
39
+1712=JPS/PNS-Ansichten, um zu tauschen
40
 2000=Wählen die Videodatei zu öffnen
41
 2001=Wählen die linke Videodatei zu öffnen
42
 2002=Wählen die rechte Videodatei zu öffnen
43
@@ -139,6 +146,8 @@
44
 2005=Löschen von Dateien
45
 ?2006=Do you really want to completely remove this file?
46
 ?2007=Active decoders:
47
+2008=Wählen die anzuhängende Audiodatei
48
+2009=Wählen die anzuhängende Untertiteldatei
49
 2010=Wählen einen Speicherort für Videoschnappschuss
50
 2011=Nichts zu speichern!
51
 2012=Schnappschuss ist nicht verfügbar!
52
@@ -253,3 +262,4 @@
53
 6055=X-Drehung - nach oben
54
 6056=X-Drehung - nach unten
55
 6057=Aktivieren / Deaktivieren der Panorama-Modus
56
+6058=GUI ausblenden
57
sview-17_04.tar.gz/StMoviePlayer/lang/korean/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/korean/StMoviePlayer.lng Changed
57
 
1
@@ -63,6 +63,7 @@
2
 ?1260=Nearest
3
 ?1261=Linear
4
 ?1262=Blend Deinterlace
5
+?1263=Trilinear
6
 1270=초기값 리셋
7
 1271=밝기
8
 ?1272=Saturation
9
@@ -71,10 +72,13 @@
10
 ?1281=Sphere
11
 ?1282=Cylinder
12
 ?1283=Cubemap
13
+?1284=Hemisphere
14
 ?1285=Track orientation
15
 ?1286=Track orientation (poor)
16
 ?1287=Orient audio
17
 ?1288=Stick at panorama 360°
18
+?1293=Equiangular cubemap
19
+?1294=Theater
20
 ?1300=Audio
21
 1301=없음
22
 1302=오디오/비디오 지연시간
23
@@ -94,9 +98,11 @@
24
 ?1359=Bottom
25
 ?1360=Plain text
26
 ?1361=Lite HTML
27
+?1370=Apply stereo format
28
 1400=장치 변경
29
 ?1401=About Plugin...
30
 ?1402=FPS 제어
31
+?1404=Exclusive Fullscreen mode
32
 ?1420=VSync
33
 ?1421=Show Meter
34
 1422=CPU 부하 감소
35
@@ -132,6 +138,7 @@
36
 ?1705=On one click windowed mode
37
 ?1710=Hide system navigation bar
38
 ?1711=Open last played file on startup
39
+?1712=Swap JPS/PNS views order
40
 2000=재생할 비디오 파일을 선택하시오
41
 2001=좌안 비디오 파일을 선택하시오
42
 2002=우안 비디오 파일을 선택하시오
43
@@ -140,6 +147,8 @@
44
 ?2005=File deletion
45
 ?2006=Do you really want to completely remove this file?
46
 ?2007=Active decoders:
47
+?2008=Choose audio file to attach
48
+?2009=Choose subtitles file to attach
49
 2010=스냅샷을 저장할 위치를 선택하시오
50
 2011=저장할 수 없음!
51
 2012=스냅샷 없음!
52
@@ -254,3 +263,4 @@
53
 ?6055=X Rotation - up
54
 ?6056=X Rotation - down
55
 ?6057=Enable/disable panorama mode
56
+?6058=Show/hide GUI
57
sview-17_04.tar.gz/StMoviePlayer/lang/russian/StMoviePlayer.lng -> sview-20_08.tar.gz/StMoviePlayer/lang/russian/StMoviePlayer.lng Changed
61
 
1
@@ -63,6 +63,7 @@
2
 1260=Без сглаживания
3
 1261=Линейное
4
 1262=Blend Deinterlace
5
+1263=Трилинейное
6
 1270=Сбросить настройки
7
 1271=Яркость
8
 1272=Насыщенность
9
@@ -71,10 +72,13 @@
10
 1281=Сфера
11
 1282=Цилиндр
12
 1283=Куб
13
+1284=Полусфера
14
 1285=Отслеживать ориентацию
15
 1286=Отслеживать ориентацию (poor)
16
 1287=Ориентировать звук
17
 1288=Закрепить панорамный режим 360°
18
+?1293=Equiangular cubemap
19
+1294=Киноэкран
20
 1300=Аудио
21
 1301=Без звука
22
 1302=Задержка звука
23
@@ -89,6 +93,7 @@
24
 1400=Выбрать устройство
25
 1401=О модуле...
26
 1402=FPS Control
27
+1404=Эксклюзивный полноэкранный режим
28
 1420=Верт. синхронизация
29
 1421=Отображать FPS
30
 1422=Ограничить использование CPU
31
@@ -121,6 +126,7 @@
32
 1359=Снизу
33
 1360=Plain text
34
 1361=Lite HTML
35
+1370=Применить стереоформат
36
 1590=Мелко
37
 1591=Нормально
38
 1592=Крупно
39
@@ -132,6 +138,7 @@
40
 1705=Только в оконном режиме
41
 1710=Скрыть панель навигации
42
 1711=Открывать последний файл при старте
43
+1712=Поменять ракурсы местами в JPS/PNS
44
 2000=Выберите видеофайл
45
 2001=Выберите видеофайл с ЛЕВЫМ ракурсом
46
 2002=Выберите видеофайл с ПРАВЫМ ракурсом
47
@@ -140,6 +147,8 @@
48
 2005=Удаление файла
49
 2006=Вы действительно хотите\n<b>удалить файл</b> минуя корзину?
50
 2007=Активные декодеры:
51
+2008=Выберите аудиофайл
52
+2009=Выберите файл субтитров
53
 2010=Выберите путь для сохранения картинки
54
 2011=Ничего не открыто!
55
 2012=Изображение недоступно для сохранения!
56
@@ -254,3 +263,4 @@
57
 6055=X наклон - наверх
58
 6056=X наклон - вниз
59
 6057=Включить/выключить панорамный режим
60
+6058=Скрыть интерфейс
61
sview-20_08.tar.gz/StMoviePlayer/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StMoviePlayer/lang/spanish/StMoviePlayer.lng Added
266
 
1
@@ -0,0 +1,264 @@
2
+# Spanish translation file for StMoviePlayer
3
+--------
4
+1002=Cambiar izquierdo/derecho
5
+1003=Revertir cambio izquierdo/derecho
6
+1004=Formato estereoscópico:
7
+1015=Abrir otra película
8
+1020=Reproducir/Pausa
9
+1021=Mostrar/Ocultar lista de reproducción
10
+1022=Reproducir archivo anterior
11
+1023=Reproducir archivo siguiente
12
+1029=Cambiar entre\npantalla completa/ventana
13
+1100=Medios
14
+1101=Abrir película...
15
+1102=Guardar instantánea...
16
+1103=Formato estereoscópico
17
+1170=Información del archivo
18
+1104=Dispositivo de audio
19
+1105=Mezclar
20
+1106=Archivos recientes
21
+1107=Decodificación de vídeo en GPU
22
+1108=UI Web
23
+1109=Salir
24
+1110=Desde un archivo
25
+1111=Archivos izquierdo+derecho
26
+1130=Fuente
27
+1131=Mono
28
+1132=Vista cruzada
29
+1133=Par paralelo
30
+1134=Sobre/bajo (D/I)
31
+1135=Sobre/bajo (I/D)
32
+1136=Entrelazado
33
+1137=Anaglifo rojo/cian
34
+1138=Anaglifo verde/rojo+azul
35
+1139=Anaglifo amarillo/azul
36
+1140=Fotograma-secuencial
37
+1141=2x720p en 1080p en mosaico
38
+1142=2 canales
39
+1160=Borrar historial
40
+1180=Apagar
41
+1181=Iniciar una vez
42
+1182=Iniciar siempre
43
+1185=Mostrar errores
44
+1186=¡No se puede iniciar la UI Web en el puerto {0}!
45
+1200=Ver
46
+1201=Salida estéreo
47
+1202=Pantalla completa
48
+1203=Restablecer
49
+1204=Cambiar izquierdo/derecho
50
+1205=Relación de visualización
51
+1206=Filtro más suave
52
+1207=Ajustar imagen
53
+1208=Panorámica
54
+1210=Estéreo
55
+1211=Vista izquierda
56
+1212=Vista derecha
57
+1213=Par paralelo
58
+1214=Vista cruzada
59
+1250=Fuente
60
+1251=Conservar al reiniciar
61
+1252=Corregir anamórfico 1080p/720p
62
+1260=Más cercano
63
+1261=Lineal
64
+1262=Mezclar entrelazado
65
+?1263=Trilineal
66
+1270=Restablecer predeterminados
67
+1271=Brillo
68
+1272=Saturación
69
+1273=Gamma
70
+1280=Plano
71
+1281=Esfera
72
+1282=Cilindro
73
+1283=Cubemap
74
+1284=Hemisferio
75
+1285=Orientación de pista
76
+1286=Orientación de pista (deficiente)
77
+1287=Orientar audio
78
+1288=Mantener en panorámica de 360°
79
+?1293=Equiangular cubemap
80
+1294=Teatro
81
+1300=Audio
82
+1301=Ninguna
83
+1302=Retraso de audio/vídeo
84
+1303=Adjuntar de archivo
85
+1320=Sincronización de audio/vídeo
86
+1321=Introduce un valor positivo si el audio está adelantado al vídeo, y negativo para lo contrario.
87
+1322=Retraso de audio:
88
+1323=segundo(s)
89
+1350=Subtítulos
90
+1351=Ninguno
91
+1353=Adjuntar de archivo
92
+1354=Tamaño de fuente
93
+1355=Paralaje
94
+1356=Interpretador de texto
95
+1357=Posición
96
+1358=Superior
97
+1359=Inferior
98
+1360=Texto sin formato
99
+1361=Lite HTML
100
+1370=Aplicar formato estéreo
101
+1400=Cambiar dispositivo
102
+1401=Acerca del complemento...
103
+1402=Control de FPS
104
+1404=Modo de pantalla completa exclusiva
105
+1420=Sincronización vertical
106
+1421=Mostrar medidor
107
+1422=Reducir uso de CPU
108
+1500=Ayuda
109
+1501=Acerca de...
110
+1502=Buscar actualizaciones
111
+1503=Texto de la licencia
112
+1504=Idioma (Language)
113
+1505=Bloquear suspensión
114
+1506=Consejos para el usuario
115
+1507=Características experimentales
116
+1508=Acerca del sistema
117
+1509=Escala de la interfaz
118
+1510=Teclas de acceso rápido
119
+1511=Ajustes
120
+1520=Ahora
121
+1521=Cada día
122
+1522=Cada semana
123
+1523=Cada año
124
+1524=Nunca
125
+1550=Nunca
126
+1551=Siempre
127
+1552=Durante la reproducción
128
+1553=En pantalla completa
129
+1590=Pequeño
130
+1591=Normal
131
+1592=Grande
132
+1593=Forzar HiDPI 2X
133
+1701=Salir de sView con escape
134
+1702=No salir
135
+1703=Con un clic
136
+1704=Con doble clic
137
+1705=Con un clic en modo ventana
138
+1710=Ocultar la barra de navegación del sistema
139
+1711=Abrir el último archivo reproducido al iniciar
140
+1712=JPS/PNS ve intercambio orden
141
+2000=Elije el archivo de vídeo para abrir
142
+2001=Elige el archivo de vídeo IZQUIERDO para abrir
143
+2002=Elije derecho archivo de vídeo DERECHO para abrir
144
+2003=Información del archivo
145
+2004=La información del archivo no está disponible
146
+2005=Eliminación de archivo
147
+2006=¿Realmente deseas eliminar completamente este archivo?
148
+2007=Descodificadores activos:
149
+2008=Elije el archivo de audio para añadir
150
+2009=Elije el archivo de subtítulos para añadir
151
+2010=Elije la ubicación para guardar la instantánea
152
+2011=¡Nada para guardar!
153
+2012=¡Instantánea no disponible!
154
+2013=Asignar nueva tecla de acceso rápido para la acción\n<i>{0}</i>
155
+2014=En conflicto con: <i>{0}</i>
156
+3000=sView - Reproductor de películas
157
+3001=versión
158
+3002=El reproductor de películas te permite reproducir un vídeo estereoscópico.\n © {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}\n\nEste programa se distribuye bajo licencia GPL 3.0
159
+3003=Hay disponible una nueva versión de sView en el sitio oficial: www.sview.ru.\nPor favor, actualiza el programa.
160
+3004=Información del sistema
161
+4000=Cerrar
162
+4001=Cancelar
163
+4005=Restablecer
164
+4006=Guardar
165
+4007=Eliminar
166
+4008=Predeterminado
167
+4009=Predeterminados
168
+4010=Asignar
169
+5000=[izquierdo]
170
+5001=[derecho]
171
+5002=Nombre de archivo(s)
172
+5003=Dimensiones del vídeo
173
+5004=Tiempo de carga
174
+5005=ms
175
+5006=Relación de pixeles
176
+5007=Formato de píxel
177
+5008=(no almacenado en los metadatos)
178
+5009=(no coincide con los metadatos)
179
+5010=Duración
180
+5011=(no almacenado en los metadatos,\npero detectado en el nombre de archivo)
181
+5300=Título
182
+5301=Compositor
183
+5302=Artista
184
+5303=Artista del álbum
185
+5304=Álbum
186
+5305=Disco
187
+5306=Núm. de discos
188
+5307=Género
189
+5308=Comentario
190
+5309=Notas
191
+5310=Descripción
192
+5311=Editor
193
+5312=Derechos de autor
194
+5313=Codificador
195
+5314=Ingeniero
196
+5315=Fuente
197
+5316=Fecha de creación
198
+5317=Fecha
199
+5318=Año
200
+5319=Idioma
201
+5320=Pista
202
+5321=Núm. de pistas
203
+5322=Ganancia de la pista
204
+5323=Pico de la pista
205
+5324=Ganancia del álbum
206
+5325=Pico del álbum
207
+6000=Salir del programa
208
+6001=Cambiar entre pantalla completa/ventana
209
+6002=Mostrar/ocultar medidor de FPS
210
+6003=Formato estéreo: Automático
211
+6004=Formato estéreo: Mono
212
+6005=Formato estéreo: Sobre/bajo
213
+6006=Formato estéreo: En paralelo
214
+6007=Mostrar información del archivo
215
+6008=Lista de reproducción: Ir al primer elemento
216
+6009=Lista de reproducción: Ir al último elemento
217
+6010=Lista de reproducción: Ir al anterior elemento
218
+6011=Lista de reproducción: Ir al siguiente elemento
219
+6012=Lista de reproducción: Ir al anterior elemento [2]
220
+6013=Lista de reproducción: Ir al siguiente elemento [2]
221
+6014=Reproducir/pausar
222
+6015=Detener reproducción
223
+6016=Atrás 5 segundos
224
+6017=Adelante 5 segundos
225
+6018=Mostrar cuadro de diálogo para abrir archivo
226
+6019=Guardar instantánea
227
+6020=Eliminar el archivo del sistema de archivos
228
+6021=Silenciar/reactivar audio
229
+6022=Bajar volumen del audio
230
+6023=Subir volumen del audio
231
+6024=Anterior pista de audio
232
+6025=Siguiente pista de audio
233
+6026=Anterior pista de subtítulos
234
+6027=Siguiente pista de subtítulos
235
+6028=Copiar el texto de los subtítulos mostrados
236
+6029=Abrir URL del portapapeles
237
+6030=Mostrar/Ocultar lista de reproducción
238
+6031=Restablecer el ajuste de la imagen
239
+6032=Restablecer la posición de la imagen
240
+6033=Cambiar izquierdo/derecho
241
+6034=Corrección gamma: disminuir
242
+6035=Corrección gamma: aumentar
243
+6036=Separación DX: disminuir
244
+6037=Separación DX: aumentar
245
+6038=Separación DY: disminuir
246
+6039=Separación DY: aumentar
247
+6040=Separación angular: disminuir
248
+6041=Separación angular: aumentar
249
+6042=Rotar 90° a la izquierda
250
+6043=Rotar 90° a la derecha
251
+6044=Rotar a la izquierda
252
+6045=Rotar a la derecha
253
+6046=Activar/Desactivar modo panorámico
254
+6047=Barrido: navegar hacia la izquierda
255
+6048=Barrido: navegar hacia la derecha
256
+6049=Barrido: navegar hacia arriba
257
+6050=Barrido: navegar hacia abajo
258
+6051=Escala: aumentar
259
+6052=Escala: reducir
260
+6053=Rotación Y: izquierda
261
+6054=Rotación Y: derecha
262
+6055=Rotación X: arriba
263
+6056=Rotación X: abajo
264
+6057=Activar/Desactivar modo panorámico
265
+6058=Mostrar/ocultar GUI
266
sview-17_04.tar.gz/StOutAnaglyph/StOutAnaglyph.cpp -> sview-20_08.tar.gz/StOutAnaglyph/StOutAnaglyph.cpp Changed
10
 
1
@@ -115,7 +115,7 @@
2
     StString& aDescr     = aLangMap.changeValueId(STTR_PLUGIN_DESCRIPTION,
3
         "(C) {0} Kirill Gavrilov <{1}>\nOfficial site: {2}\n\nThis library is distributed under LGPL3.0");
4
     myAbout = aTitle + '\n' + aVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
5
-            + aDescr.format("2007-2017", "kirill@sview.ru", "www.sview.ru");
6
+            + aDescr.format("2007-2020", "kirill@sview.ru", "www.sview.ru");
7
 }
8
 
9
 StOutAnaglyph::StOutAnaglyph(const StHandle<StResourceManager>& theResMgr,
10
sview-17_04.tar.gz/StOutAnaglyph/StOutAnaglyph.rc -> sview-20_08.tar.gz/StOutAnaglyph/StOutAnaglyph.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Anaglyph Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StOutAnaglyph\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StOutAnaglyph/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutAnaglyph/lang/spanish/StOutAnaglyph.lng Added
21
 
1
@@ -0,0 +1,19 @@
2
+# Spanish translation file for StOutAnalygph
3
+--------
4
+1000=Gafas anaglíficas
5
+1001=Gafas simples con filtros de color. Usadas comúnmente
6
+1010=Tipo de gafas
7
+1011=Rojo-cian (R+GB)
8
+1012=Amarillo-azul (RG+B)
9
+1013=Verde-magenta (G+RB)
10
+1102=Filtro rojo-cian
11
+1120=Simple
12
+1121=Optimizado
13
+1122=En gris
14
+1123=Oscuro
15
+1103=Filtro amarillo-azul
16
+1130=Simple
17
+1131=Dubios
18
+2000=sView - Módulo de salida anaglífica
19
+2001=versión
20
+2002=© {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}
21
sview-17_04.tar.gz/StOutDistorted/StOutDistorted.cpp -> sview-20_08.tar.gz/StOutDistorted/StOutDistorted.cpp Changed
566
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StOutDistorted, class providing stereoscopic output in anamorph side by side format using StCore toolkit.
4
- * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2013-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -19,6 +19,7 @@
10
 #include <StGL/StGLArbFbo.h>
11
 #include <StGLCore/StGLCore20.h>
12
 #include <StGLMesh/StGLTextureQuad.h>
13
+#include <StGLStereo/StGLProjCamera.h>
14
 #include <StSettings/StSettings.h>
15
 #include <StSettings/StTranslations.h>
16
 #include <StSettings/StEnumParam.h>
17
@@ -32,13 +33,6 @@
18
     #ifdef _MSC_VER
19
         #pragma comment(lib, "openvr_api.lib")
20
     #endif
21
-#elif defined(ST_HAVE_LIBOVR)
22
-    #include <OVR.h>
23
-    #include <OVR_CAPI_GL.h>
24
-
25
-    #ifdef _MSC_VER
26
-        #pragma comment(lib, "LibOVR.lib")
27
-    #endif
28
 #endif
29
 
30
 namespace {
31
@@ -217,7 +211,7 @@
32
 void StOutDistorted::updateAbout() {
33
     myAbout = myAboutTitle + '\n' + myAboutVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
34
             + (!myAboutVrDevice.isEmpty() ? ("Connected hardware: " + myAboutVrDevice + "\n \n") : "")
35
-            + myAboutDescr.format("2013-2017", "kirill@sview.ru", "www.sview.ru");
36
+            + myAboutDescr.format("2013-2020", "kirill@sview.ru", "www.sview.ru");
37
 #ifdef ST_HAVE_OPENVR
38
     myAbout = myAbout + "\n \n"
39
             + "This software uses OpenVR library:\n"
40
@@ -244,18 +238,15 @@
41
   myVrMarginsBottom(0.35),
42
   myVrMarginsLeft(0.33),
43
   myVrMarginsRight(0.33),
44
-  myVrRendSizeX(0),
45
-  myVrRendSizeY(0),
46
+  myVrFrequency(0),
47
+  myVrAspectRatio(1.0f),
48
+  myVrFieldOfView(-1.0f),
49
+  myVrIOD(0.0f),
50
   myVrTrackOrient(false),
51
   myVrToDrawMsg(false),
52
 #ifdef ST_HAVE_OPENVR
53
   myVrHmd(NULL),
54
   myVrTrackedPoses(new vr::TrackedDevicePose_t[vr::k_unMaxTrackedDeviceCount]),
55
-#elif defined(ST_HAVE_LIBOVR)
56
-  myVrHmd(NULL),
57
-  myOvrSwapTexture(NULL),
58
-  myOvrMirrorTexture(NULL),
59
-  myOvrMirrorFbo(0),
60
 #endif
61
   myToShowCursor(true),
62
   myToCompressMem(myInstancesNb.increment() > 1),
63
@@ -264,10 +255,6 @@
64
   myCanHdmiPack(false),
65
   myIsHdmiPack(false),
66
   myIsForcedFboUsage(false) {
67
-#ifdef ST_HAVE_LIBOVR
68
-    myOvrSwapFbo[0] = 0;
69
-    myOvrSwapFbo[1] = 0;
70
-#endif
71
     const StSearchMonitors& aMonitors = StWindow::getMonitors();
72
 
73
     // detect connected displays
74
@@ -298,13 +285,6 @@
75
     if(vr::VR_IsHmdPresent()) {
76
         aSupportOpenVr = ST_DEVICE_SUPPORT_PREFER;
77
     }
78
-#elif defined(ST_HAVE_LIBOVR)
79
-    const ovrResult anOvrRes = ovr_Initialize(NULL);
80
-    if(!OVR_SUCCESS(anOvrRes)) {
81
-        ST_ERROR_LOG("StOutDistorted, OVR initialization has failed!");
82
-    } else {
83
-        aSupportOpenVr = ST_DEVICE_SUPPORT_HIGHT;
84
-    }
85
 #endif
86
 
87
     // devices list
88
@@ -374,28 +354,6 @@
89
             vr::VR_Shutdown();
90
             myVrHmd = NULL;
91
         }
92
-    #elif defined(ST_HAVE_LIBOVR)
93
-        if(myOvrSwapFbo[0] != 0) {
94
-            myContext->arbFbo->glDeleteFramebuffers(2, myOvrSwapFbo);
95
-            myOvrSwapFbo[0] = 0;
96
-            myOvrSwapFbo[1] = 0;
97
-        }
98
-        if(myOvrSwapTexture != NULL) {
99
-            ovr_DestroySwapTextureSet(myVrHmd, myOvrSwapTexture);
100
-            myOvrSwapTexture = NULL;
101
-        }
102
-        if(myOvrMirrorFbo != 0) {
103
-            myContext->arbFbo->glDeleteFramebuffers(1, &myOvrMirrorFbo);
104
-            myOvrMirrorFbo = NULL;
105
-        }
106
-        if(myOvrMirrorTexture != NULL) {
107
-            ovr_DestroyMirrorTexture(myVrHmd, &myOvrMirrorTexture->Texture);
108
-            myOvrMirrorTexture = NULL;
109
-        }
110
-        if(myVrHmd != NULL) {
111
-            ovr_Destroy(myVrHmd);
112
-            myVrHmd = NULL;
113
-        }
114
     #endif
115
 
116
         myProgramFlat->release(*myContext);
117
@@ -437,8 +395,6 @@
118
 
119
 #ifdef ST_HAVE_OPENVR
120
     delete[] myVrTrackedPoses;
121
-#elif defined(ST_HAVE_LIBOVR)
122
-    ovr_Shutdown();
123
 #endif
124
 }
125
 
126
@@ -460,6 +416,8 @@
127
     myContext = StWindow::getContext();
128
     myContext->setMessagesQueue(myMsgQueue);
129
     myIsBroken = false;
130
+    myVrFrequency = 0;
131
+    myVrFieldOfView = -1.0f;
132
     if(!myContext->isGlGreaterEqual(2, 0)) {
133
         myMsgQueue->pushError(stCString("OpenGL 2.0 is required by Distorted Output"));
134
         myIsBroken = true;
135
@@ -538,78 +496,17 @@
136
         const StString aVrManuf   = getVrTrackedDeviceString(myVrHmd, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_ManufacturerName_String);
137
         const StString aVrDriver  = getVrTrackedDeviceString(myVrHmd, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
138
         const StString aVrDisplay = getVrTrackedDeviceString(myVrHmd, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
139
+        myVrFrequency = myVrHmd->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
140
+        updateVRProjectionFrustums();
141
 
142
-        uint32_t aRenderSizeX = 0;
143
-        uint32_t aRenderSizeY = 0;
144
+        uint32_t aRenderSizeX = 0, aRenderSizeY = 0;
145
         myVrHmd->GetRecommendedRenderTargetSize(&aRenderSizeX, &aRenderSizeY);
146
         myAboutVrDevice = aVrManuf + " " + aVrDriver + "\n"
147
-                        + aVrDisplay + " [" + aRenderSizeX + "x" + aRenderSizeY + "]";
148
-        myVrRendSizeX = int(aRenderSizeX);
149
-        myVrRendSizeY = int(aRenderSizeY);
150
+                        + aVrDisplay + " [" + aRenderSizeX + "x" + aRenderSizeY + "@" + myVrFrequency + "]";
151
+        myVrRendSize.x() = int(aRenderSizeX);
152
+        myVrRendSize.y() = int(aRenderSizeY);
153
         updateAbout();
154
     }
155
-
156
-#elif defined(ST_HAVE_LIBOVR)
157
-    if(myDevice == DEVICE_HMD) {
158
-        ovrGraphicsLuid aLuid;
159
-        const ovrResult anOvrRes = ovr_Create(&myVrHmd, &aLuid);
160
-        if(myVrHmd == NULL
161
-        || !OVR_SUCCESS(anOvrRes)) {
162
-            myMsgQueue->pushError(stCString("StOutDistorted, Oculus Rift is not connected!"));
163
-            myVrHmd = NULL;
164
-            return true;
165
-        }
166
-    }
167
-
168
-    if(myVrHmd != NULL) {
169
-        ovrHmdDesc anHmdDesc = ovr_GetHmdDesc(myVrHmd);
170
-        ovrSizei aWinSize = { anHmdDesc.Resolution.w / 2, anHmdDesc.Resolution.h / 2 };
171
-
172
-        ST_DEBUG_LOG("libOVR Resolution: " + anHmdDesc.Resolution.w + "x" + anHmdDesc.Resolution.h);
173
-        if(isMovable()) {
174
-            StRect<int32_t> aRect = StWindow::getPlacement();
175
-            aRect.right()  = aRect.left() + aWinSize.w;
176
-            aRect.bottom() = aRect.top()  + aWinSize.h;
177
-            StWindow::setPlacement(aRect, false);
178
-        }
179
-
180
-        ovrResult anOvrRes = ovr_CreateMirrorTextureGL(myVrHmd, GL_SRGB8_ALPHA8, aWinSize.w, aWinSize.h, (ovrTexture** )&myOvrMirrorTexture);
181
-        if(!OVR_SUCCESS(anOvrRes)) {
182
-            myMsgQueue->pushError(stCString("StOutDistorted, Failed to create mirror texture!"));
183
-            myIsBroken = true;
184
-            return true;
185
-        }
186
-
187
-        const GLuint anFboReadBack = myContext->stglFramebufferRead();
188
-        myContext->arbFbo->glGenFramebuffers(1, &myOvrMirrorFbo);
189
-        myContext->stglBindFramebufferRead(myOvrMirrorFbo);
190
-        myContext->arbFbo->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, myOvrMirrorTexture->OGL.TexId, 0);
191
-        myContext->stglBindFramebufferRead(anFboReadBack);
192
-
193
-        ovrSizei anEyeSizes[2] = {
194
-            ovr_GetFovTextureSize(myVrHmd, ovrEye_Left,  anHmdDesc.DefaultEyeFov[ovrEye_Left],  1),
195
-            ovr_GetFovTextureSize(myVrHmd, ovrEye_Right, anHmdDesc.DefaultEyeFov[ovrEye_Right], 1)
196
-        };
197
-        myVrRendSizeX = stMax(anEyeSizes[0].w, anEyeSizes[1].w);
198
-        myVrRendSizeY = stMax(anEyeSizes[0].h, anEyeSizes[1].h);
199
-        anOvrRes = ovr_CreateSwapTextureSetGL(myVrHmd, GL_SRGB8_ALPHA8, myVrRendSizeX * 2, myVrRendSizeY, &myOvrSwapTexture);
200
-        if(!OVR_SUCCESS(anOvrRes)
201
-         || myOvrSwapTexture->TextureCount < 2) {
202
-            myMsgQueue->pushError(stCString("StOutDistorted, Failed to create swap texture!"));
203
-            myIsBroken = true;
204
-            return true;
205
-        }
206
-
207
-        myOvrSwapTexture->CurrentIndex = 0;
208
-        myContext->arbFbo->glGenFramebuffers(2, myOvrSwapFbo);
209
-        myContext->stglBindFramebufferRead(myOvrSwapFbo[0]);
210
-        myContext->arbFbo->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
211
-                                                  ((ovrGLTexture* )&myOvrSwapTexture->Textures[0])->OGL.TexId, 0);
212
-        myContext->stglBindFramebufferRead(myOvrSwapFbo[1]);
213
-        myContext->arbFbo->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
214
-                                                  ((ovrGLTexture* )&myOvrSwapTexture->Textures[1])->OGL.TexId, 0);
215
-        myContext->stglBindFramebufferRead(anFboReadBack);
216
-    }
217
 #endif
218
 
219
     if(myDevice == DEVICE_HMD) {
220
@@ -638,6 +535,37 @@
221
     return true;
222
 }
223
 
224
+void StOutDistorted::updateVRProjectionFrustums() {
225
+#ifdef ST_HAVE_OPENVR
226
+    StRect<float> aFrustL, aFrustR;
227
+    myVrHmd->GetProjectionRaw(vr::Eye_Left,  &aFrustL.left(), &aFrustL.right(), &aFrustL.top(), &aFrustL.bottom());
228
+    myVrHmd->GetProjectionRaw(vr::Eye_Right, &aFrustR.left(), &aFrustR.right(), &aFrustR.top(), &aFrustR.bottom());
229
+    myVrFrustumL = aFrustL;
230
+    myVrFrustumR = aFrustR;
231
+    std::swap(myVrFrustumL.top(), myVrFrustumL.bottom());
232
+    std::swap(myVrFrustumR.top(), myVrFrustumR.bottom());
233
+
234
+    const StVec2<double> aTanHalfFov(StVec4<float>(-aFrustL.left(), aFrustL.right(),  -aFrustR.left(), aFrustR.right()).maxComp(),
235
+                                     StVec4<float>(-aFrustL.top(),  aFrustL.bottom(), -aFrustR.top(),  aFrustR.bottom()).maxComp());
236
+    myVrAspectRatio = float(aTanHalfFov.x() / aTanHalfFov.y());
237
+    myVrFieldOfView = float(2.0 * std::atan(aTanHalfFov.y()) * 180.0 / M_PI);
238
+
239
+    // Intra-ocular Distance can be changed in runtime
240
+    //const vr::HmdMatrix34_t aLeftToHead  = myContext->System->GetEyeToHeadTransform (vr::Eye_Left);
241
+    //const vr::HmdMatrix34_t aRightToHead = myContext->System->GetEyeToHeadTransform (vr::Eye_Right);
242
+    //myVrIOD = aRightToHead.m[0][3] - aLeftToHead.m[0][3];
243
+    myVrIOD = myVrHmd->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_UserIpdMeters_Float);
244
+#else
245
+  (void )myVrIOD;
246
+#endif
247
+}
248
+
249
+float StOutDistorted::getMaximumTargetFps() const {
250
+    return myVrFrequency > 24
251
+         ? myVrFrequency
252
+         : StWindow::getMaximumTargetFps();
253
+}
254
+
255
 void StOutDistorted::processEvents() {
256
     StWindow::processEvents();
257
 
258
@@ -694,20 +622,27 @@
259
         return;
260
     }
261
 
262
-    const float aLensDisp = getLensDist() * 0.5f;
263
-    double aGlLeft  = -1.0;
264
-    double aGlTop   =  1.0;
265
-    double aGlSizeX =  2.0;
266
-    double aGlSizeY =  2.0;
267
+    double aGlLeft  = -1.0, aGlTop   = 1.0;
268
+    double aGlSizeX =  2.0, aGlSizeY = 2.0;
269
+    float aLensDisp = theView == ST_DRAW_LEFT ? getLensDist() : -getLensDist();
270
     if(isHmdOutput()) {
271
         aGlLeft  = -1.0 + myVrMarginsLeft * 2.0;
272
         aGlTop   =  1.0 - myVrMarginsTop  * 2.0;
273
         aGlSizeX =  2.0 - (myVrMarginsLeft + myVrMarginsRight) * 2.0;
274
         aGlSizeY =  2.0 - (myVrMarginsTop + myVrMarginsBottom) * 2.0;
275
+
276
+        StGLProjCamera aProjCam;
277
+        aProjCam.setPerspective(true);
278
+        //aProjCam.setFOVy(myVrFieldOfView);
279
+        aProjCam.resize(myVrAspectRatio);
280
+        aProjCam.setCustomProjection(myVrFrustumL, myVrFrustumR);
281
+        aProjCam.setView(theView);
282
+
283
+        const StGLVec4 aTestProj = aProjCam.getProjMatrix() * StGLVec4(0, 0, aProjCam.getZScreen(), 1.0f);
284
+        aLensDisp = aTestProj.x() / aTestProj.w();
285
     }
286
 
287
     // compute cursor position
288
-    StArray<StGLVec4> aVerts(4);
289
     const float aCurLeft = float(aGlLeft + theCursorPos.x() * aGlSizeX);
290
     const float aCurTop  = float(aGlTop  - theCursorPos.y() * aGlSizeY);
291
     if(isHmdOutput()) {
292
@@ -735,17 +670,12 @@
293
                 break;
294
         }
295
     }
296
-    if(theView == ST_DRAW_LEFT) {
297
-        aVerts[0] = StGLVec4( 2.0f * aLensDisp + aCurLeft + aCurWidth, aCurTop - aCurHeight, 0.0f, 1.0f);
298
-        aVerts[1] = StGLVec4( 2.0f * aLensDisp + aCurLeft + aCurWidth, aCurTop,              0.0f, 1.0f);
299
-        aVerts[2] = StGLVec4( 2.0f * aLensDisp + aCurLeft,             aCurTop - aCurHeight, 0.0f, 1.0f);
300
-        aVerts[3] = StGLVec4( 2.0f * aLensDisp + aCurLeft,             aCurTop,              0.0f, 1.0f);
301
-    } else {
302
-        aVerts[0] = StGLVec4(-2.0f * aLensDisp + aCurLeft + aCurWidth, aCurTop - aCurHeight, 0.0f, 1.0f);
303
-        aVerts[1] = StGLVec4(-2.0f * aLensDisp + aCurLeft + aCurWidth, aCurTop,              0.0f, 1.0f);
304
-        aVerts[2] = StGLVec4(-2.0f * aLensDisp + aCurLeft,             aCurTop - aCurHeight, 0.0f, 1.0f);
305
-        aVerts[3] = StGLVec4(-2.0f * aLensDisp + aCurLeft,             aCurTop,              0.0f, 1.0f);
306
-    }
307
+
308
+    StArray<StGLVec4> aVerts(4);
309
+    aVerts[0] = StGLVec4(aLensDisp + aCurLeft + aCurWidth, aCurTop - aCurHeight, 0.0f, 1.0f);
310
+    aVerts[1] = StGLVec4(aLensDisp + aCurLeft + aCurWidth, aCurTop,              0.0f, 1.0f);
311
+    aVerts[2] = StGLVec4(aLensDisp + aCurLeft,             aCurTop - aCurHeight, 0.0f, 1.0f);
312
+    aVerts[3] = StGLVec4(aLensDisp + aCurLeft,             aCurTop,              0.0f, 1.0f);
313
     myCurVertsBuf.init(*myContext, aVerts);
314
 
315
     myContext->core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
316
@@ -767,7 +697,7 @@
317
 }
318
 
319
 bool StOutDistorted::hasOrientationSensor() const {
320
-#if defined(ST_HAVE_OPENVR) || defined(ST_HAVE_LIBOVR)
321
+#if defined(ST_HAVE_OPENVR)
322
     if(myVrHmd != NULL) {
323
         return true;
324
     }
325
@@ -776,7 +706,7 @@
326
 }
327
 
328
 bool StOutDistorted::toTrackOrientation() const {
329
-#if defined(ST_HAVE_OPENVR) || defined(ST_HAVE_LIBOVR)
330
+#if defined(ST_HAVE_OPENVR)
331
     if(myVrHmd != NULL) {
332
         return myVrTrackOrient;
333
     }
334
@@ -785,7 +715,7 @@
335
 }
336
 
337
 void StOutDistorted::setTrackOrientation(const bool theToTrack) {
338
-#if defined(ST_HAVE_OPENVR) || defined(ST_HAVE_LIBOVR)
339
+#if defined(ST_HAVE_OPENVR)
340
     if(myVrHmd != NULL) {
341
         myVrTrackOrient = theToTrack;
342
         return;
343
@@ -799,7 +729,7 @@
344
 StQuaternion<double> StOutDistorted::getDeviceOrientation() const {
345
     if(myVrTrackOrient
346
     && !myIsBroken) {
347
-    #if defined(ST_HAVE_OPENVR) || defined(ST_HAVE_LIBOVR)
348
+    #if defined(ST_HAVE_OPENVR)
349
         if(myVrHmd != NULL) {
350
             return myVrOrient;
351
         }
352
@@ -808,16 +738,35 @@
353
     return StWindow::getDeviceOrientation();
354
 }
355
 
356
+bool StOutDistorted::getCustomProjection(StRectF_t& theLeft, StRectF_t& theRight) const {
357
+    if(!isHmdOutput()) {
358
+        return false;
359
+    }
360
+
361
+    theLeft  = myVrFrustumL;
362
+    theRight = myVrFrustumR;
363
+    return true;
364
+}
365
+
366
+StGLBoxPx StOutDistorted::stglViewport(const int theWinEnum) const {
367
+    if(!isHmdOutput()) {
368
+        return StWindow::stglViewport(theWinEnum);
369
+    }
370
+
371
+    StGLBoxPx aBox;
372
+    aBox.x() = aBox.y() = 0;
373
+    aBox.width()  = myVrRendSize.x();
374
+    aBox.height() = myVrRendSize.y();
375
+    return aBox;
376
+}
377
+
378
 StMarginsI StOutDistorted::getMargins() const {
379
     if(isHmdOutput()) {
380
-        const StGLBoxPx aViewPort = StWindow::stglViewport(ST_WIN_MASTER);
381
-        const int aSizeX = aViewPort.width();
382
-        const int aSizeY = aViewPort.height();
383
         StMarginsI aMargins;
384
-        aMargins.left   = int(double(aSizeX) * myVrMarginsLeft);
385
-        aMargins.right  = int(double(aSizeX) * myVrMarginsRight);
386
-        aMargins.top    = int(double(aSizeY) * myVrMarginsTop);
387
-        aMargins.bottom = int(double(aSizeY) * myVrMarginsBottom);
388
+        aMargins.left   = int(double(myVrRendSize.x()) * myVrMarginsLeft);
389
+        aMargins.right  = int(double(myVrRendSize.x()) * myVrMarginsRight);
390
+        aMargins.top    = int(double(myVrRendSize.y()) * myVrMarginsTop);
391
+        aMargins.bottom = int(double(myVrRendSize.y()) * myVrMarginsBottom);
392
         return aMargins;
393
     }
394
     return StMarginsI();
395
@@ -832,9 +781,8 @@
396
         return StWindow::getScaleFactor();
397
     }
398
 
399
-    // within direct rendering mode HMD is not visible to the system and thus is not registered as StMonitor,
400
-    // therefore we need to override scale factor here to avoid incorrect scaling
401
-    return 0.8f;
402
+    // TODO this is calibrated for HTC Vive; applying to HMDs with another FOV might give bad results
403
+    return float(myVrRendSize.x()) / 1280.0f;
404
 }
405
 
406
 void StOutDistorted::checkHdmiPack() {
407
@@ -880,12 +828,18 @@
408
         return;
409
     }
410
 
411
-    if(!myFrBuffer->initLazy(*myContext, GL_RGBA8, myVrRendSizeX, myVrRendSizeY, StWindow::hasDepthBuffer())) {
412
-        myIsBroken = true;
413
-        myMsgQueue->pushError(stCString("OpenVR output - critical error:\nFrame Buffer Object resize failed!"));
414
-        vr::VR_Shutdown();
415
-        myVrHmd = NULL;
416
-        return;
417
+    // force resizing instead of lazy resize as we do not pass texture bounds
418
+    const vr::VRTextureBounds_t* aTexBounds = NULL;
419
+    if(!myFrBuffer->isValid()
420
+     || myFrBuffer->getSizeX() != myVrRendSize.x()
421
+     || myFrBuffer->getSizeY() != myVrRendSize.y()) {
422
+        if(!myFrBuffer->init(*myContext, GL_RGBA8, myVrRendSize.x(), myVrRendSize.y(), StWindow::hasDepthBuffer())) {
423
+            myIsBroken = true;
424
+            myMsgQueue->pushError(stCString("OpenVR output - critical error:\nFrame Buffer Object resize failed!"));
425
+            vr::VR_Shutdown();
426
+            myVrHmd = NULL;
427
+            return;
428
+        }
429
     }
430
 
431
     // draw into virtual frame buffers (textures)
432
@@ -896,7 +850,7 @@
433
         stglDrawCursor(aCursorPos, ST_DRAW_LEFT);
434
 
435
         vr::Texture_t aVRTexture = { (void* )(size_t )myFrBuffer->getTextureColor()->getTextureId(),  vr::TextureType_OpenGL, vr::ColorSpace_Gamma };
436
-        const vr::EVRCompositorError aVRError = vr::VRCompositor()->Submit(vr::Eye_Left, &aVRTexture);
437
+        const vr::EVRCompositorError aVRError = vr::VRCompositor()->Submit(vr::Eye_Left, &aVRTexture, aTexBounds);
438
         if(aVRError != vr::VRCompositorError_None) {
439
             //myMsgQueue->pushError(getVRCompositorError(aVRError));
440
             ST_ERROR_LOG(getVRCompositorError(aVRError));
441
@@ -936,8 +890,10 @@
442
                     aRotMat[aCol][aRow] = aHeadPos.m[aCol][aRow];
443
                 }
444
             }
445
+
446
             myVrOrient.setMatrix(aRotMat);
447
-         }
448
+            updateVRProjectionFrustums();
449
+        }
450
     }
451
 
452
     // real screen buffer
453
@@ -958,91 +914,6 @@
454
             myVrMsgTimer.stop();
455
         }
456
     }
457
-#elif defined(ST_HAVE_LIBOVR)
458
-    const StGLBoxPx  aVPBoth    = StWindow::stglViewport(ST_WIN_ALL);
459
-    const StPointD_t aCursorPos = getMousePos();
460
-    if(myVrHmd == NULL
461
-    || myIsBroken) {
462
-        return;
463
-    }
464
-
465
-    ovrHmdDesc anHmdDesc = ovr_GetHmdDesc(myVrHmd);
466
-    ovrEyeRenderDesc anEyeRenderDesc[2] = {
467
-        ovr_GetRenderDesc(myVrHmd, ovrEye_Left,  anHmdDesc.DefaultEyeFov[0]),
468
-        ovr_GetRenderDesc(myVrHmd, ovrEye_Right, anHmdDesc.DefaultEyeFov[1])
469
-    };
470
-    ovrViewScaleDesc aViewScaleDesc;
471
-    aViewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
472
-    aViewScaleDesc.HmdToEyeViewOffset[0] = anEyeRenderDesc[0].HmdToEyeViewOffset;
473
-    aViewScaleDesc.HmdToEyeViewOffset[1] = anEyeRenderDesc[1].HmdToEyeViewOffset;
474
-
475
-    const StGLBoxPx aViewPortL = {{ 0, 0,
476
-                                    myVrRendSizeX, myVrRendSizeY }};
477
-    const StGLBoxPx aViewPortR = {{ myVrRendSizeX, 0,
478
-                                    myVrRendSizeX, myVrRendSizeY }};
479
-
480
-    ovrLayerEyeFov aLayerFov;
481
-    aLayerFov.Header.Type       = ovrLayerType_EyeFov;
482
-    aLayerFov.Header.Flags      = ovrLayerFlag_TextureOriginAtBottomLeft;
483
-    aLayerFov.ColorTexture[0]   = myOvrSwapTexture;
484
-    aLayerFov.ColorTexture[1]   = NULL;
485
-    aLayerFov.Viewport[0].Pos.x = aViewPortL.x();
486
-    aLayerFov.Viewport[0].Pos.y = aViewPortL.y();
487
-    aLayerFov.Viewport[0].Size.w= aViewPortL.width();
488
-    aLayerFov.Viewport[0].Size.h= aViewPortL.height();
489
-    aLayerFov.Viewport[1].Pos.x = aViewPortR.x();
490
-    aLayerFov.Viewport[1].Pos.y = aViewPortR.y();
491
-    aLayerFov.Viewport[1].Size.w= aViewPortR.width();
492
-    aLayerFov.Viewport[1].Size.h= aViewPortR.height();
493
-    aLayerFov.Fov[0]            = anHmdDesc.DefaultEyeFov[0];
494
-    aLayerFov.Fov[1]            = anHmdDesc.DefaultEyeFov[1];
495
-    aLayerFov.SensorSampleTime  = ovr_GetTimeInSeconds();
496
-    const double aPredictedTime = ovr_GetPredictedDisplayTime(myVrHmd, 0);
497
-    ovrTrackingState anHmdState = ovr_GetTrackingState(myVrHmd, aPredictedTime, ovrTrue);
498
-    ovr_CalcEyePoses(anHmdState.HeadPose.ThePose, aViewScaleDesc.HmdToEyeViewOffset, aLayerFov.RenderPose);
499
-    myVrOrient = StQuaternion<double>((double )aLayerFov.RenderPose[0].Orientation.x,
500
-                                      (double )aLayerFov.RenderPose[0].Orientation.y,
501
-                                      (double )aLayerFov.RenderPose[0].Orientation.z,
502
-                                      (double )aLayerFov.RenderPose[0].Orientation.w);
503
-
504
-    // draw Left View into virtual frame buffer
505
-    myContext->stglResizeViewport(aViewPortL);
506
-    myContext->stglSetScissorRect(aViewPortL, false);
507
-    myContext->stglBindFramebuffer(myOvrSwapFbo[myOvrSwapTexture->CurrentIndex]);
508
-    StWindow::signals.onRedraw(ST_DRAW_LEFT);
509
-    stglDrawCursor(aCursorPos, ST_DRAW_LEFT);
510
-
511
-    // draw Right View into virtual frame buffer
512
-    myContext->stglResizeViewport(aViewPortR);
513
-    myContext->stglSetScissorRect(aViewPortR, false);
514
-    StWindow::signals.onRedraw(ST_DRAW_RIGHT);
515
-    stglDrawCursor(aCursorPos, ST_DRAW_RIGHT);
516
-    myContext->stglBindFramebuffer(StGLFrameBuffer::NO_FRAMEBUFFER);
517
-
518
-    ovrLayerHeader* aLayers = &aLayerFov.Header;
519
-    ovrResult anOvrRes = ovr_SubmitFrame(myVrHmd, 0, &aViewScaleDesc, &aLayers, 1);
520
-    myOvrSwapTexture->CurrentIndex = myOvrSwapTexture->CurrentIndex == 0 ? 1 : 0;
521
-    if(!OVR_SUCCESS(anOvrRes)) {
522
-        myMsgQueue->pushError(stCString("StOutDistorted, Failed to submit swap texture!"));
523
-        myIsBroken = true;
524
-    }
525
-
526
-    myContext->stglResizeViewport(aVPBoth);
527
-    myContext->stglResetScissorRect();
528
-    myContext->core20fwd->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
529
-
530
-    myContext->stglBindFramebufferRead(myOvrMirrorFbo);
531
-    myContext->stglBindFramebufferDraw(StGLFrameBuffer::NO_FRAMEBUFFER);
532
-    GLint aSrcSizeX = myOvrMirrorTexture->OGL.Header.TextureSize.w;
533
-    GLint aSrcSizeY = myOvrMirrorTexture->OGL.Header.TextureSize.h;
534
-    myContext->arbFbo->glBlitFramebuffer(0, aSrcSizeY, aSrcSizeX, 0,
535
-                                         0, 0, aVPBoth.width(), aVPBoth.height(),
536
-                                         GL_COLOR_BUFFER_BIT, GL_NEAREST);
537
-    myContext->stglBindFramebufferRead(StGLFrameBuffer::NO_FRAMEBUFFER);
538
-
539
-    myFPSControl.sleepToTarget(); // decrease FPS to target by thread sleeps
540
-    StWindow::stglSwap(ST_WIN_ALL);
541
-    ++myFPSControl;
542
 #endif
543
 }
544
 
545
@@ -1060,9 +931,8 @@
546
 
547
     double aForcedAspect = -1.0;
548
     if(isHmdOutput()) {
549
-        if(myVrRendSizeX != 0 && myVrRendSizeY != 0) {
550
-            aForcedAspect = double(myVrRendSizeX) / double(myVrRendSizeY);
551
-        }
552
+        //if(myVrRendSize.x() != 0 && myVrRendSize.y() != 0) { aForcedAspect = double(myVrRendSize.x()) / double(myVrRendSize.y()); }
553
+        aForcedAspect = myVrAspectRatio;
554
     }
555
 
556
     StWinSplit aWinSplit = StWinSlave_splitOff;
557
@@ -1117,7 +987,7 @@
558
         return;
559
     }
560
 
561
-#if defined(ST_HAVE_OPENVR) || defined(ST_HAVE_LIBOVR)
562
+#if defined(ST_HAVE_OPENVR)
563
     if(myVrHmd != NULL
564
     && !myIsBroken) {
565
         stglDrawVR();
566
sview-17_04.tar.gz/StOutDistorted/StOutDistorted.h -> sview-20_08.tar.gz/StOutDistorted/StOutDistorted.h Changed
102
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StOutDistorted, class providing stereoscopic output in anamorph side by side format using StCore toolkit.
4
- * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2013-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -28,10 +28,6 @@
10
     struct TrackedDevicePose_t;
11
 }
12
 
13
-typedef struct ovrHmdStruct* ovrSession;
14
-typedef union ovrGLTexture_s ovrGLTexture;
15
-typedef struct ovrSwapTextureSet_ ovrSwapTextureSet;
16
-
17
 /**
18
  * This class implements stereoscopic rendering on displays
19
  * which require software distortion correction.
20
@@ -131,10 +127,15 @@
21
     ST_CPPEXPORT virtual void stglDraw() ST_ATTR_OVERRIDE;
22
 
23
     /**
24
+    * Get viewport for specified subwindow.
25
+    */
26
+    ST_CPPEXPORT virtual StGLBoxPx stglViewport(const int theWinEnum) const ST_ATTR_OVERRIDE;
27
+
28
+    /**
29
      * Show/Hide mouse cursor.
30
      * @param theToShow true to show cursor
31
      */
32
-    ST_CPPEXPORT virtual void showCursor(const bool theToShow);
33
+    ST_CPPEXPORT virtual void showCursor(const bool theToShow) ST_ATTR_OVERRIDE;
34
 
35
     /**
36
      * Return true if device has orientation sensor.
37
@@ -157,6 +158,11 @@
38
     ST_CPPEXPORT virtual StQuaternion<double> getDeviceOrientation() const ST_ATTR_OVERRIDE;
39
 
40
     /**
41
+     * Return custom stereo projection frustums.
42
+     */
43
+    ST_CPPEXPORT virtual bool getCustomProjection(StRectF_t& theLeft, StRectF_t& theRight) const ST_ATTR_OVERRIDE;
44
+
45
+    /**
46
      * Return margins for working area.
47
      */
48
     ST_CPPEXPORT virtual StMarginsI getMargins() const ST_ATTR_OVERRIDE;
49
@@ -173,6 +179,11 @@
50
      */
51
     ST_LOCAL virtual void doChangeLanguage() ST_ATTR_OVERRIDE { updateStrings(); }
52
 
53
+    /**
54
+     * Return HMD framerate.
55
+     */
56
+    ST_LOCAL virtual float getMaximumTargetFps() const ST_ATTR_OVERRIDE;
57
+
58
         private:
59
 
60
     /**
61
@@ -214,6 +225,11 @@
62
             && myDevice == DEVICE_HMD;
63
     }
64
 
65
+    /**
66
+     * Retrieve active head position.
67
+     */
68
+    ST_LOCAL void updateVRProjectionFrustums();
69
+
70
         private:
71
 
72
     static StAtomic<int32_t> myInstancesNb; //!< shared counter for all instances
73
@@ -287,8 +303,13 @@
74
     double                    myVrMarginsBottom;
75
     double                    myVrMarginsLeft;
76
     double                    myVrMarginsRight;
77
-    int                       myVrRendSizeX;     //!< FBO width  for rendering into VR (can be greater then actual HMD resolution to compensate distortion)
78
-    int                       myVrRendSizeY;     //!< FBO height for rendering into VR
79
+    StRectF_t                 myVrFrustumL;      //!< projection frustum for the left eye
80
+    StRectF_t                 myVrFrustumR;      //!< projection frustum for the right eye
81
+    StVec2<int>               myVrRendSize;      //!< FBO width x height for rendering into VR (can be greater then actual HMD resolution to compensate distortion)
82
+    float                     myVrFrequency;     //!< display frequency
83
+    float                     myVrAspectRatio;   //!< aspect ratio
84
+    float                     myVrFieldOfView;   //!< field of view
85
+    float                     myVrIOD;           //!< intra-ocular distance in meters
86
     bool                      myVrTrackOrient;   //!< track orientation flag
87
     bool                      myVrToDrawMsg;
88
     StHandle<StGLTextureQuad> myVrFullscreenMsg;
89
@@ -296,12 +317,6 @@
90
 #ifdef ST_HAVE_OPENVR
91
     vr::IVRSystem*            myVrHmd;           //!< OpenVR session object
92
     vr::TrackedDevicePose_t*  myVrTrackedPoses;  //!< array of tracked devices poses
93
-#elif defined(ST_HAVE_LIBOVR)
94
-    ovrSession                myVrHmd;
95
-    ovrSwapTextureSet*        myOvrSwapTexture;
96
-    GLuint                    myOvrSwapFbo[2];
97
-    ovrGLTexture*             myOvrMirrorTexture;
98
-    GLuint                    myOvrMirrorFbo;
99
 #endif
100
 
101
     bool                      myToShowCursor;    //!< cursor visibility flag
102
sview-17_04.tar.gz/StOutDistorted/StOutDistorted.rc -> sview-20_08.tar.gz/StOutDistorted/StOutDistorted.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereo Distorted Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2013-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2013-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StOutDistorted\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StOutDistorted/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutDistorted/lang/spanish/StOutDistorted.lng Added
19
 
1
@@ -0,0 +1,17 @@
2
+# Spanish translation file for StOutDistorted
3
+--------
4
+1000=TV (par paralelo)
5
+1001=Salida distorsionada
6
+1002=OpenVR HMD
7
+1003=Distorsión de barril
8
+1110=Disposición
9
+1111=Adyacente
10
+1112=Arriba y abajo
11
+1113=Paralela (anamórfica)
12
+1114=Arriba y abajo (anamórfica)
13
+1120=Distorsión
14
+1121=Ninguna
15
+1123=Mostrar mono en estéreo
16
+2000=sView - Módulo de salida distorsionada
17
+2001=versión
18
+2002=© {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}
19
sview-17_04.tar.gz/StOutDual/StOutDual.cpp -> sview-20_08.tar.gz/StOutDual/StOutDual.cpp Changed
10
 
1
@@ -184,7 +184,7 @@
2
     StString& aDescr     = aLangMap.changeValueId(STTR_PLUGIN_DESCRIPTION,
3
         "(C) {0} Kirill Gavrilov <{1}>\nOfficial site: {2}\n\nThis library is distributed under LGPL3.0");
4
     myAbout = aTitle + '\n' + aVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
5
-            + aDescr.format("2007-2017", "kirill@sview.ru", "www.sview.ru");
6
+            + aDescr.format("2007-2020", "kirill@sview.ru", "www.sview.ru");
7
 }
8
 
9
 StOutDual::StOutDual(const StHandle<StResourceManager>& theResMgr,
10
sview-17_04.tar.gz/StOutDual/StOutDual.rc -> sview-20_08.tar.gz/StOutDual/StOutDual.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Stereo Dual Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StOutDual\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StOutDual/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutDual/lang/spanish/StOutDual.lng Added
13
 
1
@@ -0,0 +1,11 @@
2
+# Spanish translation file for StOutDual
3
+--------
4
+1000=Salida dual
5
+1001=Dispositivo estéreo con entrada dual: algunos HMD, monitores estéreo reflejados, proyectores duales
6
+1002=Salida espejo
7
+1003=Monitores estéreo reflejados hechos a mano (espejo en la dirección X)
8
+1102=Monitor esclavo
9
+1103=Mostrar mono en estéreo
10
+2000=sView - Módulo de salida dual
11
+2001=versión
12
+2002=© {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}
13
sview-17_04.tar.gz/StOutIZ3D/StOutIZ3D.cpp -> sview-20_08.tar.gz/StOutIZ3D/StOutIZ3D.cpp Changed
10
 
1
@@ -117,7 +117,7 @@
2
     StString& aDescr     = aLangMap.changeValueId(STTR_PLUGIN_DESCRIPTION,
3
         "(C) {0} Kirill Gavrilov <{1}>\nOfficial site: {2}\n\nThis library is distributed under LGPL3.0");
4
     myAbout = aTitle + '\n' + aVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
5
-            + aDescr.format("2009-2017", "kirill@sview.ru", "www.sview.ru");
6
+            + aDescr.format("2009-2020", "kirill@sview.ru", "www.sview.ru");
7
 }
8
 
9
 StOutIZ3D::StOutIZ3D(const StHandle<StResourceManager>& theResMgr,
10
sview-17_04.tar.gz/StOutIZ3D/StOutIZ3D.rc -> sview-20_08.tar.gz/StOutIZ3D/StOutIZ3D.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "IZ3D Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2009-2017 Kirill Gavrilov. Copyright \251 iZ3D LLC. All rights for codes for iZ3D conversion reserved for iZ3D LLC 2007-2009\000"
6
+      VALUE "LegalCopyright",  "\251 2009-2020 Kirill Gavrilov. Copyright \251 iZ3D LLC. All rights for codes for iZ3D conversion reserved for iZ3D LLC 2007-2009\000"
7
       VALUE "ProductName",     "StOutIZ3D\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StOutIZ3D/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutIZ3D/lang/spanish/StOutIZ3D.lng Added
13
 
1
@@ -0,0 +1,11 @@
2
+# Spanish translation file for StOutIZ3D
3
+--------
4
+1000=Visualización IZ3D
5
+1001=Visualización IZ3D
6
+1102=Gafas iZ3D
7
+1120=Clásico
8
+1121=Moderno
9
+1122=Clásico (rápido)
10
+2000=sView - Módulo de salida iZ3D
11
+2001=versión
12
+2002=© {0} Kirill Gavrilov <{1}>\n© 2007-2009 iZ3D LLC\nSitio oficial: {2}\nSitio iZ3D LLC: www.iz3d.com
13
sview-17_04.tar.gz/StOutInterlace/StOutInterlace.cpp -> sview-20_08.tar.gz/StOutInterlace/StOutInterlace.cpp Changed
484
 
1
@@ -20,6 +20,8 @@
2
 #include <StImage/StImagePlane.h>
3
 #include <StVersion.h>
4
 
5
+#include <fstream>
6
+
7
 namespace {
8
 
9
     static const char ST_OUT_PLUGIN_NAME[] = "StOutInterlace";
10
@@ -35,24 +37,40 @@
11
     struct StMonInterlacedInfo_t {
12
         const stUtf8_t* pnpid;
13
         bool            isReversed;
14
+        bool            isRowInterlaced;
15
     };
16
 
17
     /**
18
      * Database of known interlaced monitors.
19
      */
20
     static const StMonInterlacedInfo_t THE_KNOWN_MONITORS[] = {
21
-        {"ZMT1900", false}, // Zalman Trimon M190S
22
-        {"ZMT2200", false}, // Zalman Trimon M220W
23
-        {"ENV2373", true }, // Envision
24
-        {"HIT8002", false}, // Hyundai W220S D-Sub
25
-        {"HIT8D02", false}, // Hyundai W220S DVID
26
-        {"HIT7003", false}, // Hyundai W240S D-Sub
27
-        {"HIT7D03", false}, // Hyundai W240S D-Sub
28
-      //{"ACI23C2", false}, // ASUS VG23AH
29
-        {"ACI27C2", false}, // ASUS VG27AH
30
-        {       "", false}  // NULL-terminate array
31
+        {"ZMT1900", false, true}, // Zalman Trimon M190S
32
+        {"ZMT2200", false, true}, // Zalman Trimon M220W
33
+        {"ENV2373", true , true}, // Envision
34
+        {"HIT8002", false, true}, // Hyundai W220S D-Sub
35
+        {"HIT8D02", false, true}, // Hyundai W220S DVID
36
+        {"HIT7003", false, true}, // Hyundai W240S D-Sub
37
+        {"HIT7D03", false, true}, // Hyundai W240S D-Sub
38
+        {"ACI23D3", false, true}, // ASUS VG23AH
39
+        {"ACI27C2", false, true}, // ASUS VG27AH
40
+        //
41
+        {"ST@COL0", false, false}, // Android devices with parallel barrier (column-interleaved)
42
+        {       "", false, false}  // NULL-terminate array
43
     };
44
 
45
+#if defined(__ANDROID__)
46
+    // Truly / Freevi / Commander  activation
47
+    namespace mi3d_tn {
48
+        static const char* CTRL_FILE = "/dev/mi3d_tn_ctrl";
49
+        enum {
50
+            SET_TN_OFF           =  16,
51
+            SET_VERTICAL_TN_ON   =  32,
52
+            SET_HORIZONTAL_TN_ON =  64,
53
+            GET_TN_STATUS        = 128,
54
+        };
55
+    }
56
+#endif
57
+
58
     // translation resources
59
     enum {
60
         STTR_HINTERLACE_NAME    = 1000,
61
@@ -87,6 +105,24 @@
62
     static const StGLVarLocation ST_VATTRIB_VERTEX(0);
63
     static const StGLVarLocation ST_VATTRIB_TCOORD(1);
64
 
65
+    inline bool isInterlacedMonitor(const StMonitor& theMon,
66
+                                    bool&            theIsReversed,
67
+                                    bool&            theIsRowInterlaced) {
68
+        if(theMon.getPnPId().getSize() != 7) {
69
+            return false;
70
+        }
71
+        for(size_t anIter = 0;; ++anIter) {
72
+            const StMonInterlacedInfo_t& aMon = THE_KNOWN_MONITORS[anIter];
73
+            if(aMon.pnpid[0] == '\0') {
74
+                return false;
75
+            } else if(stAreEqual(aMon.pnpid, theMon.getPnPId().toCString(), 7)) {
76
+                theIsReversed      = aMon.isReversed;
77
+                theIsRowInterlaced = aMon.isRowInterlaced;
78
+                return true;
79
+            }
80
+        }
81
+    }
82
+
83
 }
84
 
85
 StProgramFB::StProgramFB(const StString& theTitle)
86
@@ -116,27 +152,12 @@
87
 
88
 StAtomic<int32_t> StOutInterlace::myInstancesNb(0);
89
 
90
-inline bool isInterlacedMonitor(const StMonitor& theMon,
91
-                                bool&            theIsReversed) {
92
-    if(theMon.getPnPId().getSize() != 7) {
93
-        return false;
94
-    }
95
-    for(size_t anIter = 0;; ++anIter) {
96
-        const StMonInterlacedInfo_t& aMon = THE_KNOWN_MONITORS[anIter];
97
-        if(aMon.pnpid[0] == '\0') {
98
-            return false;
99
-        } else if(stAreEqual(aMon.pnpid, theMon.getPnPId().toCString(), 7)) {
100
-            theIsReversed = aMon.isReversed;
101
-            return true;
102
-        }
103
-    }
104
-}
105
-
106
-StHandle<StMonitor> StOutInterlace::getHInterlaceMonitor(const StArrayList<StMonitor>& theMonitors,
107
-                                                         bool& theIsReversed) {
108
+StHandle<StMonitor> StOutInterlace::getInterlacedMonitor(const StArrayList<StMonitor>& theMonitors,
109
+                                                         bool& theIsReversed,
110
+                                                         bool& theIsRowInterlaced) {
111
     for(size_t aMonIter = 0; aMonIter < theMonitors.size(); ++aMonIter) {
112
         const StMonitor& aMon = theMonitors[aMonIter];
113
-        if(isInterlacedMonitor(aMon, theIsReversed)) {
114
+        if(isInterlacedMonitor(aMon, theIsReversed, theIsRowInterlaced)) {
115
             return new StMonitor(aMon);
116
         }
117
     }
118
@@ -153,11 +174,12 @@
119
 
120
 const char* StOutInterlace::getDeviceId() const {
121
     switch(myDevice) {
122
-        case DEVICE_COL_INTERLACED:    return "Col";
123
-        case DEVICE_CHESSBOARD:        return "Chess";
124
-        case DEVICE_ROW_INTERLACED_ED: return "RowED";
125
+        case DEVICE_COL_INTERLACED:      return "Col";
126
+        case DEVICE_COL_INTERLACED_MI3D: return "ColMI3D";
127
+        case DEVICE_CHESSBOARD:          return "Chess";
128
+        case DEVICE_ROW_INTERLACED_ED:   return "RowED";
129
         case DEVICE_ROW_INTERLACED:
130
-        default:                       return "Row";
131
+        default:                         return "Row";
132
     }
133
 }
134
 
135
@@ -166,6 +188,8 @@
136
         myDevice = DEVICE_ROW_INTERLACED;
137
     } else if(theDevice == "Col") {
138
         myDevice = DEVICE_COL_INTERLACED;
139
+    } else if(theDevice == "ColMI3D") {
140
+        myDevice = DEVICE_COL_INTERLACED_MI3D;
141
     } else if(theDevice == "Chess") {
142
         myDevice = DEVICE_CHESSBOARD;
143
     } else if(theDevice == "RowED") {
144
@@ -176,6 +200,9 @@
145
 
146
 void StOutInterlace::getDevices(StOutDevicesList& theList) const {
147
     for(size_t anIter = 0; anIter < myDevices.size(); ++anIter) {
148
+        if(myDevices[anIter]->Priority == ST_DEVICE_SUPPORT_IGNORE) {
149
+            continue;
150
+        }
151
         theList.add(myDevices[anIter]);
152
     }
153
 }
154
@@ -194,12 +221,13 @@
155
     myDevices[DEVICE_ROW_INTERLACED]   ->Desc = aLangMap.changeValueId(STTR_HINTERLACE_DESC,    "Row interlaced displays: Zalman, Hyundai,...");
156
     myDevices[DEVICE_COL_INTERLACED]   ->Name = aLangMap.changeValueId(STTR_VINTERLACE_NAME,    "Column Interlaced");
157
     myDevices[DEVICE_COL_INTERLACED]   ->Desc = aLangMap.changeValueId(STTR_VINTERLACE_DESC,    "Column interlaced displays");
158
-#if !defined(__ANDROID__)
159
     myDevices[DEVICE_CHESSBOARD]       ->Name = aLangMap.changeValueId(STTR_CHESSBOARD_NAME,    "DLP TV (chessboard)");
160
     myDevices[DEVICE_CHESSBOARD]       ->Desc = aLangMap.changeValueId(STTR_CHESSBOARD_DESC,    "DLP TV (chessboard)");
161
     myDevices[DEVICE_ROW_INTERLACED_ED]->Name = aLangMap.changeValueId(STTR_HINTERLACE_ED_NAME, "Interlaced ED");
162
     myDevices[DEVICE_ROW_INTERLACED_ED]->Desc = aLangMap.changeValueId(STTR_HINTERLACE_ED_DESC, "EDimensional in interlaced mode");
163
-#endif
164
+    myDevices[DEVICE_COL_INTERLACED_MI3D]->Name = "Interlaced [MI3D]";
165
+    myDevices[DEVICE_COL_INTERLACED_MI3D]->Desc = "Interlaced display with parallel barrier";
166
+
167
     params.ToReverse->setName(aLangMap.changeValueId(STTR_PARAMETER_REVERSE,  "Reverse Order"));
168
     params.BindToMon->setName(aLangMap.changeValueId(STTR_PARAMETER_BIND_MON, "Bind To Supported Monitor"));
169
     params.ToUseMask->setName(aLangMap.changeValueId(STTR_PARAMETER_USE_MASK, "Use texture mask (compatibility)"));
170
@@ -210,7 +238,7 @@
171
     StString& aDescr     = aLangMap.changeValueId(STTR_PLUGIN_DESCRIPTION,
172
         "(C) {0} Kirill Gavrilov <{1}>\nOfficial site: {2}\n\nThis library is distributed under LGPL3.0");
173
     myAbout = aTitle + '\n' + aVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
174
-            + aDescr.format("2009-2017", "kirill@sview.ru", "www.sview.ru");
175
+            + aDescr.format("2009-2020", "kirill@sview.ru", "www.sview.ru");
176
 }
177
 
178
 StOutInterlace::StOutInterlace(const StHandle<StResourceManager>& theResMgr,
179
@@ -222,6 +250,7 @@
180
   myTexMaskDevice(DEVICE_AUTO),
181
   myTexMaskReversed(false),
182
   myDevice(DEVICE_AUTO),
183
+  myBarrierState(BarrierState_Unknown),
184
   myEDTimer(true),
185
   myEDIntelaceOn(new StGLProgram("ED Interlace On")),
186
   myEDOff(new StGLProgram("ED Interlace Off")),
187
@@ -249,11 +278,13 @@
188
     myGlPrograms[DEVICE_COL_INTERLACED]       = new StProgramFB("Column Interlace");
189
     myGlPrograms[DEVICE_CHESSBOARD]           = new StProgramFB("Chessboard");
190
     myGlPrograms[DEVICE_ROW_INTERLACED_ED]    = myGlPrograms[DEVICE_ROW_INTERLACED];
191
+    myGlPrograms[DEVICE_COL_INTERLACED_MI3D]  = myGlPrograms[DEVICE_COL_INTERLACED];
192
 
193
-    myGlProgramsRev[DEVICE_ROW_INTERLACED]    = new StProgramFB("Row Interlace Inversed");
194
-    myGlProgramsRev[DEVICE_COL_INTERLACED]    = new StProgramFB("Column Interlace Inversed");
195
-    myGlProgramsRev[DEVICE_CHESSBOARD]        = new StProgramFB("Chessboard Inversed");
196
-    myGlProgramsRev[DEVICE_ROW_INTERLACED_ED] = myGlProgramsRev[DEVICE_ROW_INTERLACED];
197
+    myGlProgramsRev[DEVICE_ROW_INTERLACED]      = new StProgramFB("Row Interlace Inversed");
198
+    myGlProgramsRev[DEVICE_COL_INTERLACED]      = new StProgramFB("Column Interlace Inversed");
199
+    myGlProgramsRev[DEVICE_CHESSBOARD]          = new StProgramFB("Chessboard Inversed");
200
+    myGlProgramsRev[DEVICE_ROW_INTERLACED_ED]   = myGlProgramsRev[DEVICE_ROW_INTERLACED];
201
+    myGlProgramsRev[DEVICE_COL_INTERLACED_MI3D] = myGlProgramsRev[DEVICE_COL_INTERLACED];
202
 
203
     myGlProgramMask = new StProgramFB("Interlace Mask");
204
 
205
@@ -272,27 +303,56 @@
206
     aDevCol->Name     = stCString("Column Interlaced");
207
     myDevices.add(aDevCol);
208
 
209
-#if !defined(__ANDROID__)
210
     StHandle<StOutDevice> aDevChess = new StOutDevice();
211
     aDevChess->PluginId = ST_OUT_PLUGIN_NAME;
212
     aDevChess->DeviceId = stCString("Chess");
213
+#if defined(__ANDROID__)
214
+    aDevChess->Priority = ST_DEVICE_SUPPORT_IGNORE;
215
+#else
216
     aDevChess->Priority = ST_DEVICE_SUPPORT_NONE;
217
+#endif
218
     aDevChess->Name     = stCString("DLP TV (chessboard)");
219
     myDevices.add(aDevChess);
220
 
221
     StHandle<StOutDevice> aDevED = new StOutDevice();
222
     aDevED->PluginId = ST_OUT_PLUGIN_NAME;
223
     aDevED->DeviceId = stCString("RowED");
224
+#if defined(__ANDROID__)
225
+    aDevED->Priority = ST_DEVICE_SUPPORT_IGNORE;
226
+#else
227
     aDevED->Priority = ST_DEVICE_SUPPORT_NONE;
228
+#endif
229
     aDevED->Name     = stCString("Interlaced ED");
230
     myDevices.add(aDevED);
231
+
232
+    StHandle<StOutDevice> aDevMI3D = new StOutDevice();
233
+    aDevMI3D->PluginId = ST_OUT_PLUGIN_NAME;
234
+    aDevMI3D->DeviceId = stCString("ColMI3D");
235
+    aDevMI3D->Priority = ST_DEVICE_SUPPORT_IGNORE;
236
+#if defined(__ANDROID__)
237
+    {
238
+        std::fstream aCtrlFile;
239
+        aCtrlFile.open(mi3d_tn::CTRL_FILE, std::ios_base::in);
240
+        if(aCtrlFile.is_open()) {
241
+            aCtrlFile.close();
242
+            aDevMI3D->Priority = ST_DEVICE_SUPPORT_PREFER;
243
+            setBarrierState(BarrierState_Off);
244
+        }
245
+    }
246
 #endif
247
+    aDevMI3D->Name = stCString("Interlaced [MI3D]");
248
+    myDevices.add(aDevMI3D);
249
 
250
     // detect connected displays
251
-    bool isDummyReversed= false;
252
-    StHandle<StMonitor> aMonInterlaced = StOutInterlace::getHInterlaceMonitor(aMonitors, isDummyReversed);
253
+    bool isDummyReversed = false;
254
+    bool isRowInterlaced = false;
255
+    StHandle<StMonitor> aMonInterlaced = getInterlacedMonitor(aMonitors, isDummyReversed, isRowInterlaced);
256
     if(!aMonInterlaced.isNull()) {
257
-        aDevRow->Priority = ST_DEVICE_SUPPORT_PREFER;
258
+        if(isRowInterlaced) {
259
+            aDevRow->Priority = ST_DEVICE_SUPPORT_PREFER;
260
+        } else {
261
+            aDevCol->Priority = ST_DEVICE_SUPPORT_PREFER;
262
+        }
263
     }
264
 
265
     // options
266
@@ -316,7 +376,7 @@
267
         StMonitor aMonitor = aMonitors[aRect.center()];
268
         if(params.BindToMon->getValue()
269
         && !aMonInterlaced.isNull()
270
-        && !isInterlacedMonitor(aMonitor, isDummyReversed)) {
271
+        && !isInterlacedMonitor(aMonitor, isDummyReversed, isRowInterlaced)) {
272
             aMonitor = *aMonInterlaced;
273
         }
274
         if(isLoadedPosition) {
275
@@ -340,12 +400,14 @@
276
     if(!aMonInterlaced.isNull()) {
277
         myIsMonReversed = false;
278
         StMonitor aMonitor = aMonitors[StWindow::getPlacement().center()];
279
-        isInterlacedMonitor(aMonitor, myIsMonReversed);
280
+        isInterlacedMonitor(aMonitor, myIsMonReversed, isRowInterlaced);
281
     }
282
 
283
     // load device settings
284
     mySettings->loadInt32(ST_SETTING_DEVICE_ID, myDevice);
285
-    if(myDevice == DEVICE_AUTO) {
286
+    if(myDevice == DEVICE_AUTO
287
+    || myDevice >= (int )myDevices.size()
288
+    || myDevices[myDevice]->Priority == ST_DEVICE_SUPPORT_IGNORE) {
289
         myDevice = DEVICE_ROW_INTERLACED;
290
     }
291
 
292
@@ -387,6 +449,35 @@
293
     releaseResources();
294
 }
295
 
296
+void StOutInterlace::setBarrierState(BarrierState theBarrierState) {
297
+    if(myBarrierState == theBarrierState) {
298
+        return;
299
+    }
300
+
301
+    myBarrierState = theBarrierState;
302
+#if defined(__ANDROID__)
303
+    unsigned char aValue = mi3d_tn::SET_TN_OFF;
304
+    switch(myBarrierState) {
305
+        case BarrierState_Unknown:
306
+        case BarrierState_Off:
307
+            aValue = mi3d_tn::SET_TN_OFF;
308
+            break;
309
+        case BarrierState_Landscape:
310
+            aValue = mi3d_tn::SET_VERTICAL_TN_ON;
311
+            break;
312
+        case BarrierState_Portrait:
313
+            aValue = mi3d_tn::SET_HORIZONTAL_TN_ON;
314
+            break;
315
+    }
316
+    std::fstream aCtrlFile;
317
+    aCtrlFile.open(mi3d_tn::CTRL_FILE);
318
+    if(aCtrlFile.is_open()) {
319
+        aCtrlFile << aValue;
320
+        aCtrlFile.close();
321
+    }
322
+#endif
323
+}
324
+
325
 void StOutInterlace::close() {
326
     StWindow::params.VSyncMode->signals.onChanged -= stSlot(this, &StOutInterlace::doSwitchVSync);
327
     beforeClose();
328
@@ -414,6 +505,7 @@
329
             StThread::sleep(10);
330
         }
331
     }
332
+    setBarrierState(BarrierState_Off);
333
 }
334
 
335
 void StOutInterlace::show() {
336
@@ -553,15 +645,21 @@
337
     // discard mask texture
338
     StGLFragmentShader aShaderMask(myGlProgramMask->getTitle());
339
     StGLAutoRelease aTmp8(*myContext, aShaderMask);
340
-    if(!aShaderMask.init(*myContext,
341
-                         "uniform sampler2D uTexture;\n"
342
-                         "uniform sampler2D uMaskTexture;\n"
343
-                         "varying vec2 fTexCoord;\n"
344
-                         "void main(void) {\n"
345
-                         "  float aMask = texture2D(uMaskTexture, fTexCoord).a;\n"
346
-                         "  if(aMask < 0.5) { discard; }\n"
347
-                         "  gl_FragColor = texture2D(uTexture, fTexCoord);\n"
348
-                         "}\n")) {
349
+
350
+    const char* FRAGMENT_GET_ALPHA = myContext->arbTexRG
351
+                                   ? "#define stTextureAlpha(theSampler, theCoords) texture2D(theSampler, theCoords).r\n"
352
+                                   : "#define stTextureAlpha(theSampler, theCoords) texture2D(theSampler, theCoords).a\n";
353
+    const StString aMaskProgram = StString() + FRAGMENT_GET_ALPHA
354
+     + "uniform sampler2D uTexture;\n"
355
+       "uniform sampler2D uMaskTexture;\n"
356
+       "varying vec2 fTexCoord;\n"
357
+       "void main(void) {\n"
358
+       "  float aMask = stTextureAlpha(uMaskTexture, fTexCoord);\n"
359
+       "  if(aMask < 0.5) { discard; }\n"
360
+       "  gl_FragColor = texture2D(uTexture, fTexCoord);\n"
361
+       "}\n";
362
+
363
+    if(!aShaderMask.init(*myContext, aMaskProgram.toCString())) {
364
         myMsgQueue->pushError(aShadersError);
365
         myIsBroken = true;
366
         return true;
367
@@ -644,7 +742,8 @@
368
     // note that this enumeration is not enough to handle rotation direction,
369
     // which is required to automatically swap lines/columns order)
370
     myIsMonPortrait = aMon.getOrientation() == StMonitor::Orientation_Portrait;
371
-    isInterlacedMonitor(aMon, myIsMonReversed);
372
+    bool isRowInterlaced;
373
+    isInterlacedMonitor(aMon, myIsMonReversed, isRowInterlaced);
374
 }
375
 
376
 void StOutInterlace::processEvents() {
377
@@ -713,6 +812,7 @@
378
                     }
379
                     break;
380
                 }
381
+                case DEVICE_COL_INTERLACED_MI3D:
382
                 case DEVICE_COL_INTERLACED: {
383
                     if(theToReverse) {
384
                         *aPixel = (aColIter % 2 == 0) ? 255 : 0;
385
@@ -738,6 +838,11 @@
386
         }
387
     }
388
 
389
+    const GLint aTexFormat = myContext->arbTexRG ? GL_R8 : GL_ALPHA;
390
+    if(myTextureMask->getTextureFormat() != aTexFormat) {
391
+        myTextureMask->setTextureFormat(aTexFormat);
392
+    }
393
+
394
     if(!myTextureMask->init(*myContext, anImage)) {
395
         myMsgQueue->pushError(stCString("Interlace output - critical error:\nMask texture resize failed!"));
396
         myIsBroken = true;
397
@@ -808,6 +913,16 @@
398
     myContext->stglResizeViewport(aVPort);
399
     StWindow::signals.onRedraw(ST_DRAW_LEFT);
400
 
401
+    if(myIsFirstDraw) {
402
+        myIsFirstDraw = false;
403
+
404
+        // fall-back on known problematic devices
405
+        const StString aGlRenderer((const char* )myContext->core11fwd->glGetString(GL_RENDERER));
406
+        if(aGlRenderer.isContains(stCString("PowerVR Rogue G6200"))) {
407
+            params.ToUseMask->setValue(true);
408
+        }
409
+    }
410
+
411
     if(!StWindow::isStereoOutput() || myIsBroken) {
412
         if(myToCompressMem) {
413
             myFrmBuffer->release(*myContext);
414
@@ -827,6 +942,8 @@
415
                 }
416
             }
417
             stglDrawEDCodes();
418
+        } else if(myDevice == DEVICE_COL_INTERLACED_MI3D) {
419
+            setBarrierState(BarrierState_Off);
420
         }
421
 
422
         // decrease FPS to target by thread sleeps
423
@@ -836,16 +953,6 @@
424
         return;
425
     }
426
 
427
-    if(myIsFirstDraw) {
428
-        myIsFirstDraw = false;
429
-
430
-        // fall-back on known problematic devices
431
-        const StString aGlRenderer((const char* )myContext->core11fwd->glGetString(GL_RENDERER));
432
-        if(aGlRenderer.isContains(stCString("PowerVR Rogue G6200"))) {
433
-            params.ToUseMask->setValue(true);
434
-        }
435
-    }
436
-
437
     // reverse L/R according to window position
438
     bool isPixelReverse = false;
439
     const StRectI_t aWinRect = StWindow::getPlacement();
440
@@ -866,7 +973,9 @@
441
     int aDevice = myDevice;
442
 
443
     // handle portrait orientation
444
-    if(myIsMonPortrait) {
445
+    if(myDevice == DEVICE_COL_INTERLACED_MI3D) {
446
+        aDevice = DEVICE_COL_INTERLACED;
447
+    } else if(myIsMonPortrait) {
448
         switch(myDevice) {
449
             case DEVICE_ROW_INTERLACED:
450
                 aDevice = DEVICE_COL_INTERLACED;
451
@@ -892,6 +1001,7 @@
452
         switch(aDevice) {
453
             case DEVICE_CHESSBOARD:
454
             case DEVICE_COL_INTERLACED:
455
+            case DEVICE_COL_INTERLACED_MI3D:
456
                 isPixelReverse = !isPixelReverse; break;
457
         }
458
     }
459
@@ -977,6 +1087,8 @@
460
             }
461
         }
462
         stglDrawEDCodes();
463
+    } else if(myDevice == DEVICE_COL_INTERLACED_MI3D) {
464
+        setBarrierState(myIsMonPortrait ? BarrierState_Portrait : BarrierState_Landscape);
465
     }
466
 
467
     // decrease FPS to target by thread sleeps
468
@@ -1003,12 +1115,13 @@
469
     const StSearchMonitors& aMonitors = StWindow::getMonitors();
470
     StRectI_t aRect = StWindow::getPlacement();
471
     StMonitor aMon  = aMonitors[aRect.center()];
472
-    if(isInterlacedMonitor(aMon, myIsMonReversed)
473
+    bool isRowInterlaced = false;
474
+    if(isInterlacedMonitor(aMon, myIsMonReversed, isRowInterlaced)
475
     || !isMovable()) {
476
         return;
477
     }
478
 
479
-    StHandle<StMonitor> anInterlacedMon = StOutInterlace::getHInterlaceMonitor(aMonitors, myIsMonReversed);
480
+    StHandle<StMonitor> anInterlacedMon = getInterlacedMonitor(aMonitors, myIsMonReversed, isRowInterlaced);
481
     if(anInterlacedMon.isNull()) {
482
         return;
483
     }
484
sview-17_04.tar.gz/StOutInterlace/StOutInterlace.h -> sview-20_08.tar.gz/StOutInterlace/StOutInterlace.h Changed
63
 
1
@@ -118,19 +118,24 @@
2
         private:
3
 
4
     enum {
5
-        DEVICE_AUTO              =-1,
6
-        DEVICE_ROW_INTERLACED    = 0, //!< interlace (horizontal 1xPixel lines, full color from R or L)
7
-        DEVICE_COL_INTERLACED    = 1, //!< interlace (vertical 1xPixel lines, full color from R or L)
8
-        DEVICE_CHESSBOARD        = 2, //!< 1xPixel chessboard (some DLP devices)
9
-        DEVICE_ROW_INTERLACED_ED = 3, //!< interlace (horizontal 1xPixel lines) + EDimensional onscreen codes
10
+        DEVICE_AUTO                =-1,
11
+        DEVICE_ROW_INTERLACED      = 0, //!< interlace (horizontal 1xPixel lines, full color from R or L)
12
+        DEVICE_COL_INTERLACED      = 1, //!< interlace (vertical 1xPixel lines, full color from R or L)
13
+        DEVICE_CHESSBOARD          = 2, //!< 1xPixel chessboard (some DLP devices)
14
+        DEVICE_ROW_INTERLACED_ED   = 3, //!< interlace (horizontal 1xPixel lines) + EDimensional onscreen codes
15
+        DEVICE_COL_INTERLACED_MI3D = 4, //!< interlace with barrier
16
 
17
         DEVICE_NB,
18
     };
19
 
20
         private:
21
 
22
-    ST_LOCAL static StHandle<StMonitor> getHInterlaceMonitor(const StArrayList<StMonitor>& theMonitors,
23
-                                                             bool& theIsReversed);
24
+    /**
25
+     * Look for interlaced monitors within the given list.
26
+     */
27
+    ST_LOCAL static StHandle<StMonitor> getInterlacedMonitor(const StArrayList<StMonitor>& theMonitors,
28
+                                                             bool& theIsReversed,
29
+                                                             bool& theIsRowInterlaced);
30
 
31
     ST_LOCAL void stglDrawEDCodes();
32
 
33
@@ -181,6 +186,21 @@
34
 
35
     } params;
36
 
37
+    /**
38
+     * Parallax barrier state.
39
+     */
40
+    enum BarrierState {
41
+        BarrierState_Unknown = -1,
42
+        BarrierState_Off     = 0,
43
+        BarrierState_Landscape,
44
+        BarrierState_Portrait,
45
+    };
46
+
47
+    /**
48
+     * Initialize parallax barrier state.
49
+     */
50
+    void setBarrierState(BarrierState theBarrierState);
51
+
52
         private:
53
 
54
     StOutDevicesList          myDevices;
55
@@ -200,6 +220,7 @@
56
     StGLVertexBuffer          myQuadTexCoordBuf;
57
     int                       myDevice;
58
     StHandle<StMonitor>       myMonitor;                  //!< current monitor
59
+    BarrierState              myBarrierState;
60
 
61
     StRectI_t                 myWinRect;
62
     StRectI_t                 myEDRect;
63
sview-17_04.tar.gz/StOutInterlace/StOutInterlace.rc -> sview-20_08.tar.gz/StOutInterlace/StOutInterlace.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "Interlace Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2009-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2009-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StOutInterlace\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-20_08.tar.gz/StOutInterlace/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutInterlace/lang/spanish/StOutInterlace.lng Added
18
 
1
@@ -0,0 +1,16 @@
2
+# Spanish translation file for StOutInterlaced
3
+--------
4
+1000=Filas entrelazadas
5
+1001=Pantallas con filas entrelazadas: Zalman, Hyundai...
6
+1002=Columnas entrelazadas
7
+1003=Pantallas con columnas entrelazadas
8
+1006=DLP TV (tablero de ajedrez)
9
+1007=DLP TV (tablero de ajedrez)
10
+1008=ED entrelazado
11
+1009=EDimensional en modo entrelazado
12
+1102=Orden inverso
13
+1103=Enlazar con monitor compatible
14
+1104=Usar máscara de textura (compatibilidad)
15
+2000=sView - Módulo de salida entrelazada
16
+2001=versión
17
+2002=© {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}
18
sview-17_04.tar.gz/StOutPageFlip/StDXNVWindow.cpp -> sview-20_08.tar.gz/StOutPageFlip/StDXNVWindow.cpp Changed
35
 
1
@@ -112,19 +112,22 @@
2
                                       LPARAM theParamL) {
3
     // we do stupid checks here...
4
     if(myStWin->isFullScreen() && myStWin->isStereoOutput()) {
5
-        if(theMsg == WM_MOUSEWHEEL) {
6
-            int zDelta = GET_WHEEL_DELTA_WPARAM(theParamW);
7
+        if(theMsg == WM_MOUSEWHEEL
8
+        || theMsg == WM_MOUSEHWHEEL) {
9
+            const bool  isVert   = (theMsg == WM_MOUSEWHEEL);
10
+            const int   aZDelta  = GET_WHEEL_DELTA_WPARAM(theParamW);
11
+            const int   aNbSteps = (aZDelta > 0) ? 1 : -1;
12
+            const float aDeltaSt = float(aZDelta) / float(WHEEL_DELTA);
13
             const StPointD_t aPnt = myStWin->getMousePos();
14
             StEvent anEvent;
15
-            anEvent.Type = stEvent_Scroll;
16
-            anEvent.Scroll.Time   = 0.0; //getEventTime(myEvent.time);
17
-            anEvent.Scroll.PointX = aPnt.x();
18
-            anEvent.Scroll.PointY = aPnt.y();
19
-            anEvent.Scroll.StepsX = 0;
20
-            anEvent.Scroll.StepsY = (zDelta > 0) ? 1 : -1;
21
-            anEvent.Scroll.DeltaX = 0.0;
22
-            anEvent.Scroll.DeltaY = 10.0f * anEvent.Scroll.StepsY;
23
-            anEvent.Scroll.IsFromMultiTouch = false;
24
+            anEvent.Scroll.init(0.0, //getEventTime(myEvent.time);
25
+                                aPnt.x(),
26
+                                aPnt.y(),
27
+                                !isVert ? aDeltaSt : 0.0f,
28
+                                 isVert ? aDeltaSt : 0.0f,
29
+                                false);
30
+            anEvent.Scroll.StepsX = !isVert ? aNbSteps : 0;
31
+            anEvent.Scroll.StepsY =  isVert ? aNbSteps : 0;
32
             myStWin->post(anEvent);
33
         }
34
 
35
sview-17_04.tar.gz/StOutPageFlip/StOutPageFlip.cpp -> sview-20_08.tar.gz/StOutPageFlip/StOutPageFlip.cpp Changed
56
 
1
@@ -357,7 +357,7 @@
2
 
3
 static StMonitor getHigestFreqMonitor(const StSearchMonitors& theMonitors) {
4
     size_t hfreqMon = 0;
5
-    int hfreqMax = 0;
6
+    float hfreqMax = 0;
7
     for(size_t aMonIter = 0; aMonIter < theMonitors.size(); ++aMonIter) {
8
         const StMonitor& aMon = theMonitors[aMonIter];
9
         if(aMon.getFreqMax() > hfreqMax) {
10
@@ -484,7 +484,7 @@
11
     StString& aDescr     = myLangMap.changeValueId(STTR_PLUGIN_DESCRIPTION,
12
         "(C) {0} Kirill Gavrilov <{1}>\nOfficial site: {2}\n\nThis library is distributed under LGPL3.0");
13
     myAbout = aTitle + '\n' + aVerString + " " + StVersionInfo::getSDKVersionString() + "\n \n"
14
-            + aDescr.format("2007-2017", "kirill@sview.ru", "www.sview.ru");
15
+            + aDescr.format("2007-2020", "kirill@sview.ru", "www.sview.ru");
16
 }
17
 
18
 StOutPageFlip::StOutPageFlip(const StHandle<StResourceManager>& theResMgr,
19
@@ -617,7 +617,7 @@
20
     // read windowed placement
21
     StWindow::hide();
22
     if(isMovable()) {
23
-        StWindow::setFullScreen(false);
24
+        setFullScreen(false);
25
     }
26
 }
27
 
28
@@ -742,7 +742,7 @@
29
             // Direct3D device will fail to Reset if GL fullscreen device is active
30
             // so we switch out main GL window into windowed state temporarily
31
             // (we need to wait some time to ensure system perform needed movements)
32
-            StWindow::setFullScreen(false);
33
+            setFullScreen(false);
34
             StWindow::hide();
35
             ++myOutD3d.ActivateStep;
36
             return;
37
@@ -754,7 +754,7 @@
38
         if(myOutD3d.ActivateStep == 1) {
39
             // at second step switch out main GL window back to fullscreen
40
             myOutD3d.ActivateStep = 0;
41
-            StWindow::setFullScreen(true);
42
+            setFullScreen(true);
43
             StWindow::hide();
44
 
45
             if(myOutD3d.WglDxBuffer.isNull()
46
@@ -853,6 +853,9 @@
47
 
48
     // request Quad Buffer
49
     StWindow::setAttribute(StWinAttr_GlQuadStereo, params.QuadBuffer->getValue() == QUADBUFFER_HARD_OPENGL);
50
+    if (params.QuadBuffer->getValue() == QUADBUFFER_SOFT) {
51
+        StWindow::setAttribute(StWinAttr_ExclusiveFullScreen, true);
52
+    }
53
     if(!StWindow::create()) {
54
         return false;
55
     }
56
sview-17_04.tar.gz/StOutPageFlip/StOutPageFlip.rc -> sview-20_08.tar.gz/StOutPageFlip/StOutPageFlip.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "PageFlip Renderer library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StOutPageFlip\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StOutPageFlip/StOutPageFlipExt.cpp -> sview-20_08.tar.gz/StOutPageFlip/StOutPageFlipExt.cpp Changed
15
 
1
@@ -138,6 +138,13 @@
2
     return true;
3
 }
4
 
5
+void StOutPageFlipExt::setFullScreen(const bool theFullScreen) {
6
+    if(StOutPageFlip::params.QuadBuffer->getValue() == QUADBUFFER_SOFT) {
7
+        setAttribute(StWinAttr_ExclusiveFullScreen, true);
8
+    }
9
+    StOutPageFlip::setFullScreen(theFullScreen);
10
+}
11
+
12
 void StOutPageFlipExt::processEvents() {
13
     StOutPageFlip::processEvents();
14
     if(!StOutPageFlip::params.ToShowExtra->getValue()) {
15
sview-17_04.tar.gz/StOutPageFlip/StOutPageFlipExt.h -> sview-20_08.tar.gz/StOutPageFlip/StOutPageFlipExt.h Changed
13
 
1
@@ -53,6 +53,11 @@
2
     ST_CPPEXPORT virtual void processEvents() ST_ATTR_OVERRIDE;
3
 
4
     /**
5
+     * @param theFullScreen fullscreen state
6
+     */
7
+    ST_CPPEXPORT virtual void setFullScreen(const bool theFullScreen) ST_ATTR_OVERRIDE;
8
+
9
+    /**
10
      * Retrieve options list.
11
      */
12
     ST_CPPEXPORT virtual void getOptions(StParamsList& theList) const ST_ATTR_OVERRIDE;
13
sview-17_04.tar.gz/StOutPageFlip/StQuadBufferCheck.cpp -> sview-20_08.tar.gz/StOutPageFlip/StQuadBufferCheck.cpp Changed
15
 
1
@@ -36,6 +36,13 @@
2
     return (RegisterClassW(&aClass) != 0);
3
 }
4
 #elif !defined(__APPLE__) && !defined(ST_HAVE_EGL)
5
+    // exclude modern definitions and system-provided glext.h, should be defined before gl.h inclusion
6
+    #ifndef GL_GLEXT_LEGACY
7
+        #define GL_GLEXT_LEGACY
8
+    #endif
9
+    #ifndef GLX_GLXEXT_LEGACY
10
+        #define GLX_GLXEXT_LEGACY
11
+    #endif
12
     #include <GL/glx.h>
13
 #endif
14
 
15
sview-20_08.tar.gz/StOutPageFlip/lang/spanish Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/StOutPageFlip/lang/spanish/StOutPageFlip.lng Added
26
 
1
@@ -0,0 +1,24 @@
2
+# Spanish translation file for StOutPageFlip
3
+--------
4
+1000=Gafas de obturador
5
+1001=Gafas de obturador
6
+1002=Vuzix HMD
7
+1003=Vuzix HMD
8
+1102=Tipo búfer cuádruple
9
+1103=Códigos de control de gafas
10
+1120=OpenGL emulado
11
+1122=OpenGL por hardware
12
+1123=Direct3D (Pantalla completa)
13
+1124=Direct3D (No disponible)
14
+1125=Direct3D AMD (Pantalla completa)
15
+1126=Direct3D AMD (No disponible)
16
+1127=Direct3D NVIDIA (Pantalla completa)
17
+1128=Direct3D NVIDIA (Desactivado)
18
+1130=Sin códigos
19
+1131=Sincronización de línea azul
20
+1132=Sincronización de línea blanca
21
+1134=Apagado/encendido automático de eDimensional
22
+2000=sView - Módulo de salida PageFlip
23
+2001=versión
24
+2002=© {0} Kirill Gavrilov <{1}>\nSitio oficial: {2}
25
+3001=¡El búfer cuádruple OpenGL por hardware no está disponible!\n\nPuedes probar otro tipo de búfer cuádruple\n(Incluido OpenGL emulado en la sección Extra).
26
sview-17_04.tar.gz/StShared/StAVFrame.cpp -> sview-20_08.tar.gz/StShared/StAVFrame.cpp Changed
18
 
1
@@ -36,6 +36,16 @@
2
 #endif
3
 }
4
 
5
+int64_t StAVFrame::getBestEffortTimestamp() const {
6
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 81, 102)) && !defined(ST_LIBAV_FORK)
7
+    return Frame->best_effort_timestamp;
8
+#elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 18, 100)) && !defined(ST_LIBAV_FORK)
9
+    return av_frame_get_best_effort_timestamp(Frame);
10
+#else
11
+    return stAV::NOPTS_VALUE;
12
+#endif
13
+}
14
+
15
 void StAVFrame::getImageInfo(const AVCodecContext* theCodecCtx,
16
                              int&           theSizeX,
17
                              int&           theSizeY,
18
sview-17_04.tar.gz/StShared/StAVIOContext.cpp -> sview-20_08.tar.gz/StShared/StAVIOContext.cpp Changed
10
 
1
@@ -48,7 +48,7 @@
2
 StAVIOContext::StAVIOContext()
3
 : myAvioCtx(NULL) {
4
     const int aBufferSize = 32768;
5
-    unsigned char* aBufferIO = (unsigned char* )av_malloc(aBufferSize + FF_INPUT_BUFFER_PADDING_SIZE);
6
+    unsigned char* aBufferIO = (unsigned char* )av_malloc(aBufferSize + AV_INPUT_BUFFER_PADDING_SIZE);
7
     myAvioCtx = avio_alloc_context(aBufferIO, aBufferSize, 0, this, readCallback, writeCallback, seekCallback);
8
 }
9
 
10
sview-20_08.tar.gz/StShared/StAVIOJniHttpContext.cpp Added
417
 
1
@@ -0,0 +1,415 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#include <StAV/StAVIOJniHttpContext.h>
11
+
12
+#include <StStrings/StLogger.h>
13
+
14
+extern "C" {
15
+    #include <libavutil/error.h>
16
+};
17
+
18
+#if defined(__ANDROID__)
19
+    extern "C" {
20
+        #include <libavcodec/jni.h>
21
+    };
22
+    #include <android/window.h>
23
+    #include <jni.h>
24
+
25
+/**
26
+ * java.net.URLConnection wrapper.
27
+ */
28
+struct StAVIOJniHttpContext::FunctionTable {
29
+
30
+    /**
31
+     * Create java.nio.channels.ReadableByteChannel by opening java.net.URLConnection to specified URL.
32
+     * @param theJEnv   [in] attached JavaVM environment
33
+     * @param theUrl    [in] URL to open
34
+     * @param theOffset [in] file offset
35
+     * @param theContentLen [out] file length
36
+     * @return local reference to java.nio.channels.ReadableByteChannel
37
+     */
38
+    jobject createNewChannel(StJNIEnv& theJEnv,
39
+                             const StString& theUrl,
40
+                             int64_t theOffset,
41
+                             int64_t& theContentLen) {
42
+        theJEnv->ExceptionClear();
43
+        jobject aJInputStream = createInputStream(theJEnv, theUrl, theOffset, theContentLen);
44
+        if(aJInputStream == NULL) {
45
+            return NULL;
46
+        }
47
+        jobject aJReadChannel = theJEnv->CallStaticObjectMethod(myNioChannels_Class, myNioChannels_newChannel, aJInputStream);
48
+        theJEnv->DeleteLocalRef(aJInputStream);
49
+        return aJReadChannel;
50
+    }
51
+
52
+    /**
53
+     * Read portion of data from opened channel.
54
+     * @sa int java.nio.channels.ReadableByteChannel::read(java.nio.ByteBuffer theBuffer).
55
+     * @param theJEnv    [in] attached JavaVM environment
56
+     * @param theChannel [in] opened channel java.nio.channels.ReadableByteChannel
57
+     * @param theBuf    [out] buffer to fill
58
+     * @param theBufSize [in] buffer length
59
+     * @return amount of bytes read from channel or -1 on error/EOF; could be also 0 bytes.
60
+     */
61
+    int readChannelIntoBuffer(StJNIEnv& theJEnv,
62
+                              jobject theChannel,
63
+                              uint8_t* theBuf,
64
+                              int theBufSize) {
65
+        theJEnv->ExceptionClear();
66
+        jobject aJBuffer = theJEnv->NewDirectByteBuffer(theBuf, theBufSize);
67
+        if(aJBuffer == NULL) {
68
+            return -1;
69
+        }
70
+
71
+        int aNbReadBytes = theJEnv->CallIntMethod(theChannel, myNioReadableByteChannel_read, aJBuffer);
72
+        theJEnv->DeleteLocalRef(aJBuffer);
73
+        if(theJEnv->ExceptionCheck()) {
74
+            theJEnv->ExceptionClear();
75
+            return -1;
76
+        }
77
+        return aNbReadBytes;
78
+    }
79
+
80
+    /**
81
+     * Load functions.
82
+     */
83
+    bool load(StJNIEnv& theJEnv) {
84
+        if(!myjava_net_URL.load(theJEnv)) {
85
+            return false;
86
+        }
87
+
88
+        jclass aClass = theJEnv->FindClass("java/net/URLConnection");
89
+        if(aClass == NULL) {
90
+            ST_ERROR_LOG("Unable to find java.net.URLConnection class");
91
+            return false;
92
+        }
93
+
94
+        myconnect = theJEnv->GetMethodID(aClass, "connect", "()V");
95
+        mysetRequestProperty = theJEnv->GetMethodID(aClass, "setRequestProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
96
+        mygetInputStream = theJEnv->GetMethodID(aClass, "getInputStream", "()Ljava/io/InputStream;");
97
+        mygetContentLength = theJEnv->GetMethodID(aClass, "getContentLength", "()I");
98
+        mygetContentLengthLong = theJEnv->GetMethodID(aClass, "getContentLengthLong", "()J");
99
+        if(myconnect == NULL || mysetRequestProperty == NULL || mygetInputStream == NULL || mygetContentLength == NULL) {
100
+            ST_ERROR_LOG("Unable to find java.net.URLConnection class methods");
101
+            return false;
102
+        }
103
+
104
+        myNioChannels_Class      = theJEnv->FindClass("java/nio/channels/Channels");
105
+        myNioChannels_newChannel = theJEnv->GetStaticMethodID(myNioChannels_Class, "newChannel",
106
+                                                              "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
107
+        if(myNioChannels_Class == NULL
108
+        || myNioChannels_newChannel == NULL) {
109
+            ST_ERROR_LOG("Unable to find java.nio.channels.Channels class");
110
+            return false;
111
+        }
112
+        myNioChannels_Class = (jclass )theJEnv->NewGlobalRef(myNioChannels_Class);
113
+
114
+        jclass aNioReadableByteChannel_Class = theJEnv->FindClass("java/nio/channels/ReadableByteChannel");
115
+        myNioReadableByteChannel_read = aNioReadableByteChannel_Class != NULL
116
+                                      ? theJEnv->GetMethodID(aNioReadableByteChannel_Class, "read", "(Ljava/nio/ByteBuffer;)I")
117
+                                      : NULL;
118
+        if(myNioReadableByteChannel_read == NULL) {
119
+            ST_ERROR_LOG("Unable to find java.nio.channels.ReadableByteChannel class");
120
+            return false;
121
+        }
122
+        return true;
123
+    }
124
+
125
+    /**
126
+     * Release global references (to Java classes).
127
+     */
128
+    void release(StJNIEnv& theJEnv) {
129
+        myjava_net_URL.release(theJEnv);
130
+        if(myNioChannels_Class != NULL) {
131
+            theJEnv->DeleteGlobalRef(myNioChannels_Class);
132
+            myNioChannels_Class = NULL;
133
+        }
134
+    }
135
+
136
+        private:
137
+
138
+    /**
139
+     * Create java.io.InputStream by opening java.net.URLConnection to specified URL.
140
+     * @param theJEnv   [in] attached JavaVM environment
141
+     * @param theUrl    [in] URL to open
142
+     * @param theOffset [in] file offset
143
+     * @param theContentLen [out] file length
144
+     * @return local reference to java.io.InputStream
145
+     */
146
+    jobject createInputStream(StJNIEnv& theJEnv,
147
+                              const StString& theUrl,
148
+                              int64_t theOffset,
149
+                              int64_t& theContentLen) {
150
+        jobject aJConnection = myjava_net_URL.openConnection(theJEnv, theUrl);
151
+        if(aJConnection == NULL) {
152
+            return NULL;
153
+        }
154
+
155
+        if(theOffset != 0) {
156
+            StString anOffset = StString("bytes=") + theOffset + "-";
157
+            jstring aJStr_Range  = theJEnv->NewStringUTF("Range");
158
+            jstring aJStr_Offset = theJEnv->NewStringUTF(anOffset.toCString());
159
+            theJEnv->CallVoidMethod(aJConnection, mysetRequestProperty, aJStr_Range, aJStr_Offset);
160
+            theJEnv->DeleteLocalRef(aJStr_Range);
161
+            theJEnv->DeleteLocalRef(aJStr_Offset);
162
+        }
163
+        theJEnv->CallVoidMethod(aJConnection, myconnect);
164
+        if(theJEnv->ExceptionCheck()) {
165
+            ST_ERROR_LOG("Unable to open connection java.net.URLConnection '" + theUrl + "'");
166
+            theJEnv->ExceptionClear();
167
+            theJEnv->DeleteLocalRef(aJConnection);
168
+            return NULL;
169
+        }
170
+
171
+        if(mygetContentLengthLong != NULL) {
172
+            theContentLen = theJEnv->CallLongMethod(aJConnection, mygetContentLengthLong);
173
+        } else {
174
+            theContentLen = theJEnv->CallIntMethod(aJConnection, mygetContentLength);
175
+        }
176
+
177
+        jobject aJInputStream = theJEnv->CallObjectMethod(aJConnection, mygetInputStream);
178
+        theJEnv->DeleteLocalRef(aJConnection);
179
+        if(theJEnv->ExceptionCheck()) {
180
+            theJEnv->ExceptionClear();
181
+            if(aJInputStream != NULL) {
182
+                theJEnv->DeleteLocalRef(aJInputStream);
183
+                aJInputStream = NULL;
184
+            }
185
+        }
186
+        if(aJInputStream == NULL) {
187
+            ST_ERROR_LOG("Unable to create java.io.InputStream");
188
+        }
189
+        return aJInputStream;
190
+    }
191
+
192
+    // java.net.URL wrapper.
193
+    struct st_java_net_URL {
194
+
195
+        /**
196
+         * Load java.net.URL class and its methods.
197
+         */
198
+        bool load(StJNIEnv& theJEnv) {
199
+            myClass = theJEnv->FindClass("java/net/URL");
200
+            if(myClass == NULL) {
201
+                ST_ERROR_LOG("Unable to find java.net.URL class");
202
+                return false;
203
+            }
204
+
205
+            myClass = (jclass )theJEnv->NewGlobalRef(myClass);
206
+            myInit = theJEnv->GetMethodID(myClass, "<init>", "(Ljava/lang/String;)V");
207
+            myopenConnection = theJEnv->GetMethodID(myClass, "openConnection", "()Ljava/net/URLConnection;");
208
+            if(myInit == NULL || myopenConnection == NULL) {
209
+                ST_ERROR_LOG("Unable to find java.net.URL class methods");
210
+                release(theJEnv);
211
+                return false;
212
+            }
213
+            return true;
214
+        }
215
+
216
+        /**
217
+         * Release global references (to Java class).
218
+         */
219
+        void release(StJNIEnv& theJEnv) {
220
+            if(myClass != NULL) {
221
+                theJEnv->DeleteGlobalRef(myClass);
222
+                myClass = NULL;
223
+            }
224
+        }
225
+
226
+        /**
227
+         * Create java.net.URLConnection opening specified URL.
228
+         * Return local reference or NULL on failure.
229
+         */
230
+        jobject openConnection(StJNIEnv& theJEnv, const StString& theUrl) {
231
+            jobject aJNetUrl = create(theJEnv, theUrl);
232
+            if(aJNetUrl == NULL) {
233
+                ST_ERROR_LOG("Unable to create java.net.URL");
234
+                return NULL;
235
+            }
236
+
237
+            jobject aJNetUrlCon = theJEnv->CallObjectMethod(aJNetUrl, myopenConnection);
238
+            theJEnv->DeleteLocalRef(aJNetUrl);
239
+            if(theJEnv->ExceptionCheck()) {
240
+                theJEnv->ExceptionClear();
241
+                if(aJNetUrlCon != NULL) {
242
+                    theJEnv->DeleteLocalRef(aJNetUrlCon);
243
+                    aJNetUrlCon = NULL;
244
+                }
245
+            }
246
+            if(aJNetUrlCon == NULL) {
247
+                ST_ERROR_LOG("Unable to create java.net.URLConnection");
248
+                return NULL;
249
+            }
250
+            return aJNetUrlCon;
251
+        }
252
+
253
+            private:
254
+
255
+        /**
256
+         * Create java.net.URL class instance with specified URL; returns local reference.
257
+         */
258
+        jobject create(StJNIEnv& theJEnv, const StString& theUrl) {
259
+            jstring aJStr_Url = theJEnv->NewStringUTF(theUrl.toCString());
260
+            jobject aNetURL = theJEnv->NewObject(myClass, myInit, aJStr_Url);
261
+            theJEnv->DeleteLocalRef(aJStr_Url);
262
+            return aNetURL;
263
+        }
264
+
265
+            private:
266
+
267
+        jclass    myClass = NULL;
268
+        jmethodID myInit  = NULL;
269
+        jmethodID myopenConnection = NULL;
270
+
271
+    } myjava_net_URL;
272
+
273
+    // java.net.URLConnection
274
+    jmethodID myconnect = NULL;
275
+    jmethodID mysetRequestProperty = NULL;
276
+    jmethodID mygetInputStream = NULL;
277
+    jmethodID mygetContentLength = NULL;
278
+    jmethodID mygetContentLengthLong = NULL;
279
+
280
+    // java.nio.channels.Channels
281
+    jclass    myNioChannels_Class = NULL;
282
+    jmethodID myNioChannels_newChannel = NULL;
283
+
284
+    //java.nio.channels.ReadableByteChannel
285
+    //myNioReadableByteChannel_Class = NULL
286
+    jmethodID myNioReadableByteChannel_read = NULL;
287
+
288
+};
289
+#endif
290
+
291
+StAVIOJniHttpContext::StAVIOJniHttpContext()
292
+: myFunctions(NULL),
293
+#if defined(__ANDROID__)
294
+  myJEnv((JavaVM* )av_jni_get_java_vm(NULL)),
295
+#else
296
+  myJEnv(NULL),
297
+#endif
298
+  myReadChannel(NULL),
299
+  myContentLen(0),
300
+  myPosition(0) {
301
+#if defined(__ANDROID__)
302
+    if(!myJEnv.isNull()) {
303
+        myFunctions = new FunctionTable();
304
+        if(!myFunctions->load(myJEnv)) {
305
+            myFunctions->release(myJEnv);
306
+            myJEnv.detach();
307
+        }
308
+    }
309
+#endif
310
+}
311
+
312
+StAVIOJniHttpContext::~StAVIOJniHttpContext() {
313
+    close();
314
+    if(myFunctions != NULL) {
315
+    #if defined(__ANDROID__)
316
+        myFunctions->release(myJEnv);
317
+        delete myFunctions;
318
+    #endif
319
+    }
320
+}
321
+
322
+void StAVIOJniHttpContext::close() {
323
+    if(myReadChannel != NULL) {
324
+    #if defined(__ANDROID__)
325
+        myJEnv->DeleteGlobalRef((jobject )myReadChannel);
326
+    #endif
327
+        myReadChannel = NULL;
328
+    }
329
+}
330
+
331
+bool StAVIOJniHttpContext::reopenReadChannel(int64_t theOffset) {
332
+    if(myJEnv.isNull()) {
333
+        return false;
334
+    }
335
+
336
+#if defined(__ANDROID__)
337
+    if(myReadChannel != NULL) {
338
+        myJEnv->DeleteGlobalRef((jobject )myReadChannel);
339
+        myReadChannel = NULL;
340
+    }
341
+
342
+    /**
343
+     * java.net.URL anUrl = new java.net.URL(aPath);
344
+     * java.net.URLConnection anUrlConnection = anUrl.openConnection();
345
+     * anUrlConnection.setRequestProperty ("Range", "bytes="+offset+"-");
346
+     * anUrlConnection.connect();
347
+     * java.io.InputStream anInputStream = anUrlConnection.getInputStream();
348
+     * java.nio.channels.ReadableByteChannel aReadableByteChannel = java.nio.channels.Channels.newChannel(anInputStream);
349
+     */
350
+    jobject aJReadChannel = myFunctions->createNewChannel(myJEnv, myUrl, theOffset, myContentLen);
351
+    if(aJReadChannel == NULL) {
352
+        myReadChannel = NULL;
353
+        return false;
354
+    }
355
+    myReadChannel = myJEnv->NewGlobalRef(aJReadChannel);
356
+    myPosition = theOffset;
357
+    return true;
358
+#else
359
+    (void )theOffset;
360
+    return false;
361
+#endif
362
+}
363
+
364
+bool StAVIOJniHttpContext::open(const StString& theUrl) {
365
+    close();
366
+    myUrl = theUrl;
367
+    return reopenReadChannel(0);
368
+}
369
+
370
+int StAVIOJniHttpContext::read(uint8_t* theBuf,
371
+                               int      theBufSize) {
372
+    if(myReadChannel == NULL
373
+    || theBuf == NULL
374
+    || theBufSize <= 0) {
375
+        return -1;
376
+    }
377
+
378
+#if defined(__ANDROID__)
379
+    int aNbRead = myFunctions->readChannelIntoBuffer(myJEnv, (jobject )myReadChannel, theBuf, theBufSize);
380
+    if(aNbRead == -1) {
381
+        return AVERROR_EOF;
382
+    }
383
+    return aNbRead;
384
+#else
385
+    return -1;
386
+#endif
387
+}
388
+
389
+int64_t StAVIOJniHttpContext::seek(int64_t theOffset,
390
+                                   int     theWhence) {
391
+    if(myReadChannel == NULL) {
392
+        return -1;
393
+    }
394
+
395
+    switch(theWhence) {
396
+        case AVSEEK_SIZE: {
397
+            return myContentLen != 0 ? myContentLen : -1;
398
+        }
399
+        case SEEK_SET: {
400
+            reopenReadChannel(theOffset);
401
+            return myPosition;
402
+        }
403
+        case SEEK_CUR: {
404
+            reopenReadChannel(myPosition + theOffset);
405
+            return myPosition;
406
+        }
407
+        case SEEK_END: {
408
+            if(myContentLen <= 0) {
409
+                return -1;
410
+            }
411
+            reopenReadChannel(myContentLen + theOffset);
412
+            return myPosition;
413
+        }
414
+    }
415
+    return -1;
416
+}
417
sview-17_04.tar.gz/StShared/StAVImage.cpp -> sview-20_08.tar.gz/StShared/StAVImage.cpp Changed
239
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -46,7 +46,8 @@
9
         }
10
     }
11
     switch(theImage.getColorModel()) {
12
-        case StImage::ImgColor_YUV: {
13
+        case StImage::ImgColor_YUV:
14
+        case StImage::ImgColor_YUVA: {
15
             size_t aDelimX = (theImage.getPlane(1).getSizeX() > 0) ? (aPlane0.getSizeX() / theImage.getPlane(1).getSizeX()) : 1;
16
             size_t aDelimY = (theImage.getPlane(1).getSizeY() > 0) ? (aPlane0.getSizeY() / theImage.getPlane(1).getSizeY()) : 1;
17
             if(theImage.getPlane(1).getFormat() == StImagePlane::ImgUV) {
18
@@ -101,7 +102,7 @@
19
                 }
20
             } else if(aDelimX == 1 && aDelimY == 2) {
21
                 return theImage.getColorScale() == StImage::ImgScale_Mpeg
22
-                     ? stAV::PIX_FMT::YUVJ440P : stAV::PIX_FMT::YUV440P;
23
+                     ? stAV::PIX_FMT::YUV440P : stAV::PIX_FMT::YUVJ440P;
24
             } else if(aDelimX == 4 && aDelimY == 1) {
25
                 return stAV::PIX_FMT::YUV411P;
26
             } else if(aDelimX == 4 && aDelimY == 4) {
27
@@ -121,12 +122,16 @@
28
     }
29
 }
30
 
31
+static const int THE_SWSCALE_FLAGS_FAST    = SWS_BICUBIC;
32
+static const int THE_SWSCALE_FLAGS_QUALITY = SWS_LANCZOS | SWS_ACCURATE_RND | SWS_FULL_CHR_H_INT;
33
+
34
 /**
35
  * Convert image from one format to another using swscale.
36
  * Image buffers should be already initialized!
37
  */
38
 static bool convert(const StImage& theImageFrom, AVPixelFormat theFormatFrom,
39
-                          StImage& theImageTo,   AVPixelFormat theFormatTo) {
40
+                          StImage& theImageTo,   AVPixelFormat theFormatTo,
41
+                    int theSwsFlags) {
42
     ST_DEBUG_LOG("StAVImage, convert from " + stAV::PIX_FMT::getString(theFormatFrom) + " " + theImageFrom.getSizeX() + "x" + theImageFrom.getSizeY()
43
                + " to " + stAV::PIX_FMT::getString(theFormatTo) + " " + theImageTo.getSizeX() + "x" + theImageTo.getSizeY());
44
     if(theFormatFrom == stAV::PIX_FMT::NONE
45
@@ -136,7 +141,7 @@
46
 
47
     SwsContext* aCtxToRgb = sws_getContext((int )theImageFrom.getSizeX(), (int )theImageFrom.getSizeY(), theFormatFrom, // source
48
                                            (int )theImageTo.getSizeX(),   (int )theImageTo.getSizeY(),   theFormatTo,   // destination
49
-                                           SWS_BICUBIC, NULL, NULL, NULL);
50
+                                           theSwsFlags, NULL, NULL, NULL);
51
     if(aCtxToRgb == NULL) {
52
         return false;
53
     }
54
@@ -156,6 +161,59 @@
55
     return true;
56
 }
57
 
58
+/**
59
+ * Return AV pixel format for an image plane.
60
+ */
61
+static int getAVPixelFormatForPlane(const StImagePlane& theImage) {
62
+    switch(theImage.getFormat()) {
63
+        case StImagePlane::ImgRGB:    return stAV::PIX_FMT::RGB24;
64
+        case StImagePlane::ImgBGR:    return stAV::PIX_FMT::BGR24;
65
+        case StImagePlane::ImgRGBA:   return stAV::PIX_FMT::RGBA32;
66
+        case StImagePlane::ImgBGRA:   return stAV::PIX_FMT::BGRA32;
67
+        case StImagePlane::ImgGray:   return stAV::PIX_FMT::GRAY8;
68
+        case StImagePlane::ImgGray16: return stAV::PIX_FMT::GRAY16;
69
+        default:                      return stAV::PIX_FMT::NONE;
70
+    }
71
+}
72
+
73
+bool StAVImage::resizePlane(const StImagePlane& theImageFrom,
74
+                            StImagePlane&       theImageTo) {
75
+    if(theImageFrom.isNull()
76
+    || theImageFrom.getSizeX() < 1
77
+    || theImageFrom.getSizeY() < 1
78
+    || theImageTo.isNull()
79
+    || theImageTo.getSizeX() < 1
80
+    || theImageTo.getSizeY() < 1) {
81
+        return false;
82
+    }
83
+
84
+    StAVImage::init();
85
+    const AVPixelFormat aFormatFrom = (AVPixelFormat )getAVPixelFormatForPlane(theImageFrom);
86
+    const AVPixelFormat aFormatTo   = (AVPixelFormat )getAVPixelFormatForPlane(theImageTo);
87
+    if(aFormatFrom == stAV::PIX_FMT::NONE
88
+    || aFormatTo   == stAV::PIX_FMT::NONE) {
89
+        return false;
90
+    }
91
+
92
+    SwsContext* aCtxToRgb = sws_getContext((int )theImageFrom.getSizeX(), (int )theImageFrom.getSizeY(), aFormatFrom,
93
+                                           (int )theImageTo.getSizeX(),   (int )theImageTo.getSizeY(),   aFormatTo,
94
+                                           THE_SWSCALE_FLAGS_FAST, NULL, NULL, NULL);
95
+    if(aCtxToRgb == NULL) {
96
+        return false;
97
+    }
98
+
99
+    uint8_t* aSrcData[4] = { (uint8_t* )theImageFrom.getData(), NULL, NULL, NULL };
100
+    int  aSrcLinesize[4] = { (int )theImageFrom.getSizeRowBytes(), 0, 0, 0 };
101
+    uint8_t* aDstData[4] = { (uint8_t* )theImageTo.getData(), NULL, NULL, NULL };
102
+    int  aDstLinesize[4] = { (int )theImageTo.getSizeRowBytes(), 0, 0, 0 };
103
+    sws_scale(aCtxToRgb,
104
+              aSrcData, aSrcLinesize,
105
+              0, (int )theImageFrom.getSizeY(),
106
+              aDstData, aDstLinesize);
107
+    sws_freeContext(aCtxToRgb);
108
+    return true;
109
+}
110
+
111
 bool StAVImage::resize(const StImage& theImageFrom,
112
                        StImage&       theImageTo) {
113
     if(theImageFrom.isNull()
114
@@ -173,7 +231,8 @@
115
     return aFormatFrom != stAV::PIX_FMT::NONE
116
         && aFormatTo   != stAV::PIX_FMT::NONE
117
         && convert(theImageFrom, aFormatFrom,
118
-                   theImageTo,   aFormatTo);
119
+                   theImageTo,   aFormatTo,
120
+                   THE_SWSCALE_FLAGS_FAST);
121
 }
122
 
123
 void StAVImage::close() {
124
@@ -235,6 +294,10 @@
125
             myCodec = avcodec_find_decoder_by_name("webp");
126
             break;
127
         }
128
+        case ST_TYPE_DDS: {
129
+            myCodec = avcodec_find_decoder_by_name("dds");
130
+            break;
131
+        }
132
         default: {
133
             break;
134
         }
135
@@ -258,7 +321,7 @@
136
     #endif
137
         if(avErrCode != 0
138
         || myFormatCtx->nb_streams < 1
139
-        || myFormatCtx->streams[0]->codec->codec_id == 0) {
140
+        || stAV::getCodecId(myFormatCtx->streams[0]) == AV_CODEC_ID_NONE) {
141
             if(myFormatCtx != NULL) {
142
             #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0))
143
                 avformat_close_input(&myFormatCtx);
144
@@ -289,7 +352,7 @@
145
         }
146
 
147
         // find the decoder for the video stream
148
-        myCodecCtx = myFormatCtx->streams[0]->codec;
149
+        myCodecCtx = stAV::getCodecCtx(myFormatCtx->streams[0]);
150
         if(theImageType == ST_TYPE_NONE) {
151
             myCodec = avcodec_find_decoder(myCodecCtx->codec_id);
152
         }
153
@@ -353,7 +416,12 @@
154
 
155
     // decode one frame
156
     int isFrameFinished = 0;
157
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
158
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
159
+    if(avcodec_send_packet(myCodecCtx, anAvPkt.getAVpkt()) == 0
160
+    && avcodec_receive_frame(myCodecCtx, myFrame.Frame) == 0) {
161
+        isFrameFinished = 1;
162
+    }
163
+#elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
164
     avcodec_decode_video2(myCodecCtx, myFrame.Frame, &isFrameFinished, anAvPkt.getAVpkt());
165
 #else
166
     avcodec_decode_video(myCodecCtx, myFrame.Frame, &isFrameFinished,
167
@@ -472,7 +540,7 @@
168
             aDimsYUV.isFullScale = true;
169
         }
170
     #endif
171
-        setColorModel(StImage::ImgColor_YUV);
172
+        setColorModel(aDimsYUV.hasAlpha ? StImage::ImgColor_YUVA : StImage::ImgColor_YUV);
173
         setColorScale(aDimsYUV.isFullScale ? StImage::ImgScale_Full : StImage::ImgScale_Mpeg);
174
         StImagePlane::ImgFormat aPlaneFrmt = StImagePlane::ImgGray;
175
         if(aDimsYUV.bitsPerComp == 9) {
176
@@ -491,6 +559,10 @@
177
                                    size_t(aDimsYUV.widthU), size_t(aDimsYUV.heightU), myFrame.getLineSize(1));
178
         changePlane(2).initWrapper(aPlaneFrmt, myFrame.getPlane(2),
179
                                    size_t(aDimsYUV.widthV), size_t(aDimsYUV.heightV), myFrame.getLineSize(2));
180
+        if(aDimsYUV.hasAlpha) {
181
+            changePlane(3).initWrapper(aPlaneFrmt, myFrame.getPlane(3),
182
+                                       size_t(aDimsYUV.widthY), size_t(aDimsYUV.heightY), myFrame.getLineSize(3));
183
+        }
184
     } else {
185
         ///ST_DEBUG_LOG("StAVImage, perform conversion from Pixel format '" + avcodec_get_pix_fmt_name(myCodecCtx->pix_fmt) + "' to RGB");
186
         // initialize software scaler/converter
187
@@ -566,7 +638,8 @@
188
                 anImage.changePlane().initTrash(StImagePlane::ImgRGB, getSizeX(), getSizeY(), getAligned(getSizeX() * 3));
189
                 AVPixelFormat aPFrmtTarget = stAV::PIX_FMT::RGB24;
190
                 if(!convert(*this,   aPFormatAV,
191
-                            anImage, aPFrmtTarget)) {
192
+                            anImage, aPFrmtTarget,
193
+                            THE_SWSCALE_FLAGS_QUALITY)) {
194
                     setState("SWScale library, failed to create SWScaler context");
195
                     close();
196
                     return false;
197
@@ -616,7 +689,8 @@
198
                 anImage.changePlane(2).initTrash(StImagePlane::ImgGray, getSizeX(), getSizeY(), getAligned(getSizeX()));
199
                 stMemSet(anImage.changePlane(2).changeData(), '\0', anImage.getPlane(2).getSizeBytes());
200
                 if(!convert(*this,   aPFormatAV,
201
-                            anImage, aPFrmtTarget)) {
202
+                            anImage, aPFrmtTarget,
203
+                            THE_SWSCALE_FLAGS_QUALITY)) {
204
                     setState("SWScale library, failed to create SWScaler context");
205
                     close();
206
                     return false;
207
@@ -681,12 +755,20 @@
208
         return false;
209
     }
210
 
211
+    // encode the image
212
+    StAVPacket aPacket;
213
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
214
+    int anEncSize = 0;
215
+    if(avcodec_send_frame(myCodecCtx, myFrame.Frame) == 0
216
+    && avcodec_receive_packet(myCodecCtx, aPacket.getAVpkt()) == 0
217
+    && aPacket.getAVpkt()->data != NULL) {
218
+        anEncSize = aPacket.getSize();
219
+        aRawFile.wrapBuffer(aPacket.getAVpkt()->data, anEncSize);
220
+    }
221
+#else
222
     // allocate the buffer, large enough (stupid formula copied from ffmpeg.c)
223
     int aBuffSize = int(getSizeX() * getSizeY() * 10);
224
     aRawFile.initBuffer(aBuffSize);
225
-
226
-    // encode the image
227
-    StAVPacket aPacket;
228
     aPacket.getAVpkt()->data = (uint8_t* )aRawFile.changeBuffer();
229
     aPacket.getAVpkt()->size = aBuffSize;
230
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 2, 100))
231
@@ -698,6 +780,7 @@
232
 #else
233
     int anEncSize = avcodec_encode_video(myCodecCtx, aPacket.changeData(), aPacket.getSize(), myFrame.Frame);
234
 #endif
235
+#endif
236
     if(anEncSize <= 0) {
237
         setState("AVCodec library, fail to encode the image");
238
         close();
239
sview-17_04.tar.gz/StShared/StAVPacket.cpp -> sview-20_08.tar.gz/StShared/StAVPacket.cpp Changed
61
 
1
@@ -64,7 +64,11 @@
2
   myIsOwn(false) {
3
     avInitPacket();
4
     if(myType == DATA_PACKET) {
5
+    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 106, 102))
6
+        av_packet_ref(&myPacket, &theCopy.myPacket); // copy by reference
7
+    #else
8
         setAVpkt(theCopy.myPacket);
9
+    #endif
10
     }
11
 }
12
 
13
@@ -75,17 +79,21 @@
14
 void StAVPacket::free() {
15
     if(myIsOwn) {
16
         avDestructPacket(&myPacket);
17
+        avInitPacket();
18
     } else {
19
-    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
20
+    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100))
21
+        av_packet_unref(&myPacket);
22
+    #elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0))
23
         av_free_packet(&myPacket);
24
+        avInitPacket();
25
     #else
26
         if(myPacket.destruct != NULL) {
27
             myPacket.destruct(&myPacket);
28
             myPacket.destruct = NULL;
29
         }
30
+        avInitPacket();
31
     #endif
32
     }
33
-    avInitPacket();
34
     myIsOwn = false;
35
 }
36
 
37
@@ -104,9 +112,9 @@
38
 #endif
39
 
40
     // now copy data with special padding space
41
-    myPacket.data = stMemAllocAligned<uint8_t*>((theCopy.size + FF_INPUT_BUFFER_PADDING_SIZE), 16); // data must be aligned to 16 bytes for SSE!
42
+    myPacket.data = stMemAllocAligned<uint8_t*>((theCopy.size + AV_INPUT_BUFFER_PADDING_SIZE), 16); // data must be aligned to 16 bytes for SSE!
43
     stMemCpy (myPacket.data, theCopy.data, theCopy.size);
44
-    stMemZero(myPacket.data + (ptrdiff_t )theCopy.size, FF_INPUT_BUFFER_PADDING_SIZE);
45
+    stMemZero(myPacket.data + (ptrdiff_t )theCopy.size, AV_INPUT_BUFFER_PADDING_SIZE);
46
 
47
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 118, 0))
48
     if(myPacket.side_data_elems > 0) {
49
@@ -117,9 +125,9 @@
50
         for(int anIter = 0; anIter < theCopy.side_data_elems; ++anIter) {
51
             aSize = theCopy.side_data[anIter].size;
52
             myPacket.side_data[anIter] = theCopy.side_data[anIter];
53
-            myPacket.side_data[anIter].data = stMemAllocAligned<uint8_t*>(aSize + FF_INPUT_BUFFER_PADDING_SIZE, 16);
54
+            myPacket.side_data[anIter].data = stMemAllocAligned<uint8_t*>(aSize + AV_INPUT_BUFFER_PADDING_SIZE, 16);
55
             stMemCpy (myPacket.side_data[anIter].data, theCopy.side_data[anIter].data, aSize);
56
-            stMemZero(myPacket.side_data[anIter].data + (ptrdiff_t )aSize, FF_INPUT_BUFFER_PADDING_SIZE);
57
+            stMemZero(myPacket.side_data[anIter].data + (ptrdiff_t )aSize, AV_INPUT_BUFFER_PADDING_SIZE);
58
         }
59
     }
60
 #endif
61
sview-17_04.tar.gz/StShared/StAVVideoMuxer.cpp -> sview-20_08.tar.gz/StShared/StAVVideoMuxer.cpp Changed
125
 
1
@@ -194,16 +194,18 @@
2
 
3
 bool StAVVideoMuxer::addStream(AVFormatContext* theContext,
4
                                AVStream*        theStream) {
5
+    AVCodecContext* aCodecCtxSrc = stAV::getCodecCtx(theStream);
6
 #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0))
7
-    AVStream* aStreamOut = avformat_new_stream(theContext, theStream->codec->codec);
8
+    AVStream* aStreamOut = avformat_new_stream(theContext, aCodecCtxSrc->codec);
9
 #else
10
-    AVStream* aStreamOut = avformat_new_stream(theContext, (AVCodec* )theStream->codec->codec);
11
+    AVStream* aStreamOut = avformat_new_stream(theContext, (AVCodec* )aCodecCtxSrc->codec);
12
 #endif
13
     if(aStreamOut == NULL) {
14
         signals.onError(StString("Failed allocating output stream."));
15
         return false;
16
     }
17
-    if(avcodec_copy_context(aStreamOut->codec, theStream->codec) < 0) {
18
+    AVCodecContext* aCodecCtxNew = stAV::getCodecCtx(aStreamOut);
19
+    if(avcodec_copy_context(aCodecCtxNew, aCodecCtxSrc) < 0) {
20
         signals.onError(StString("Failed to copy context from input to output stream codec context."));
21
         return false;
22
     }
23
@@ -211,13 +213,13 @@
24
 //#if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(54, 2, 100))
25
 //    myIsAttachedPic = (theStream->disposition & AV_DISPOSITION_ATTACHED_PIC) != 0;
26
 //#endif
27
-    if(theStream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
28
-        aStreamOut->sample_aspect_ratio        = theStream->sample_aspect_ratio;
29
-        aStreamOut->codec->sample_aspect_ratio = aStreamOut->sample_aspect_ratio;
30
+    if(aCodecCtxSrc->codec_type == AVMEDIA_TYPE_VIDEO) {
31
+        aStreamOut->sample_aspect_ratio   = theStream->sample_aspect_ratio;
32
+        aCodecCtxNew->sample_aspect_ratio = aStreamOut->sample_aspect_ratio;
33
     }
34
 
35
     if(theContext->oformat->flags & AVFMT_GLOBALHEADER) {
36
-        aStreamOut->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
37
+        aCodecCtxNew->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
38
     }
39
     return true;
40
 }
41
@@ -254,7 +256,7 @@
42
         for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
43
             aCtxSrc.Streams.add((unsigned int )-1);
44
             AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
45
-            if(aStreamSrc->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
46
+            if(stAV::getCodecType(aStreamSrc) == AVMEDIA_TYPE_VIDEO) {
47
                 if(addStream(aCtxOut.Context, aStreamSrc)) {
48
                     aCtxSrc.Streams[aStreamId] = aStreamCount++;
49
                 }
50
@@ -268,7 +270,7 @@
51
         StRemuxContext& aCtxSrc = aSrcCtxList[aCtxId];
52
         for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
53
             AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
54
-            if(aStreamSrc->codec->codec_type == AVMEDIA_TYPE_AUDIO
55
+            if(stAV::getCodecType(aStreamSrc) == AVMEDIA_TYPE_AUDIO
56
             && addStream(aCtxOut.Context, aStreamSrc)) {
57
                 aCtxSrc.Streams[aStreamId] = aStreamCount++;
58
             }
59
@@ -280,8 +282,8 @@
60
         StRemuxContext& aCtxSrc = aSrcCtxList[aCtxId];
61
         for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
62
             AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
63
-            if(aStreamSrc->codec->codec_type != AVMEDIA_TYPE_VIDEO
64
-            && aStreamSrc->codec->codec_type != AVMEDIA_TYPE_AUDIO
65
+            if(stAV::getCodecType(aStreamSrc) != AVMEDIA_TYPE_VIDEO
66
+            && stAV::getCodecType(aStreamSrc) != AVMEDIA_TYPE_AUDIO
67
             && addStream(aCtxOut.Context, aStreamSrc)) {
68
                 aCtxSrc.Streams[aStreamId] = aStreamCount++;
69
             }
70
@@ -303,7 +305,7 @@
71
         return false;
72
     }
73
 
74
-    AVPacket aPacket;
75
+    StAVPacket aPacket;
76
     for(;;) {
77
         size_t aNbEmpty = 0;
78
         for(size_t aCtxId = 0; aCtxId < aSrcCtxList.size(); ++aCtxId) {
79
@@ -313,18 +315,18 @@
80
                 continue;
81
             }
82
 
83
-            if(av_read_frame(aCtxSrc.Context, &aPacket) < 0) {
84
+            if(av_read_frame(aCtxSrc.Context, aPacket.getAVpkt()) < 0) {
85
                 aCtxSrc.State = false;
86
                 ++aNbEmpty;
87
                 continue;
88
             }
89
 
90
-            unsigned int aStreamOutIndex = aCtxSrc.Streams[aPacket.stream_index];
91
+            unsigned int aStreamOutIndex = aCtxSrc.Streams[aPacket.getStreamId()];
92
             if(aStreamOutIndex == (unsigned int )-1) {
93
                 continue;
94
             }
95
 
96
-            AVStream* aStreamIn  = aCtxSrc.Context->streams[aPacket.stream_index];
97
+            AVStream* aStreamIn  = aCtxSrc.Context->streams[aPacket.getStreamId()];
98
             AVStream* aStreamOut = aCtxOut.Context->streams[aStreamOutIndex];
99
 
100
         #ifdef ST_LIBAV_FORK
101
@@ -332,17 +334,17 @@
102
         #else
103
             const AVRounding aRoundParams = AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
104
         #endif
105
-            aPacket.pts      = av_rescale_q_rnd(aPacket.pts, aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
106
-            aPacket.dts      = av_rescale_q_rnd(aPacket.dts, aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
107
-            aPacket.duration = static_cast<int >(av_rescale_q(aPacket.duration, aStreamIn->time_base, aStreamOut->time_base));
108
-            aPacket.pos      = -1;
109
+            aPacket.getAVpkt()->pts      = av_rescale_q_rnd(aPacket.getPts(), aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
110
+            aPacket.getAVpkt()->dts      = av_rescale_q_rnd(aPacket.getDts(), aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
111
+            aPacket.getAVpkt()->duration = static_cast<int >(av_rescale_q(aPacket.getDuration(), aStreamIn->time_base, aStreamOut->time_base));
112
+            aPacket.getAVpkt()->pos      = -1;
113
 
114
-            aState = av_interleaved_write_frame(aCtxOut.Context, &aPacket);
115
+            aState = av_interleaved_write_frame(aCtxOut.Context, aPacket.getAVpkt());
116
             if(aState < 0) {
117
                 signals.onError(StString("Error muxing packet (") + stAV::getAVErrorDescription(aState) + ").");
118
                 return false;
119
             }
120
-            av_free_packet(&aPacket);
121
+            aPacket.free();
122
         }
123
         if(aNbEmpty == aSrcCtxList.size()) {
124
             break;
125
sview-17_04.tar.gz/StShared/StAction.cpp -> sview-20_08.tar.gz/StShared/StAction.cpp Changed
25
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -11,12 +11,11 @@
9
 
10
 StAction::StAction(const StCString& theName)
11
 : myName(theName),
12
-  myHotKey1(0),
13
-  myHotKey2(0),
14
-  myDefaultHotKey1(0),
15
-  myDefaultHotKey2(0),
16
   myToHoldKey(false) {
17
-    //
18
+    myHotKeys[0] = 0;
19
+    myHotKeys[1] = 0;
20
+    myHotKeysDef[0] = 0;
21
+    myHotKeysDef[1] = 0;
22
 }
23
 
24
 StAction::~StAction() {}
25
sview-17_04.tar.gz/StShared/StCocoaCoords.mm -> sview-20_08.tar.gz/StShared/StCocoaCoords.mm Changed
11
 
1
@@ -42,7 +42,9 @@
2
     CGDirectDisplayID aDispId = [aNumber unsignedIntValue];
3
     CGRect aRect = CGDisplayBounds(aDispId);
4
     myScreenBottom = aRect.origin.y + aRect.size.height;
5
+ST_DISABLE_DEPRECATION_WARNINGS
6
     myScale        = [aScreen userSpaceScaleFactor];
7
+ST_ENABLE_DEPRECATION_WARNINGS
8
     myUnScale      = 1.0 / myScale;
9
     return true;
10
 }
11
sview-17_04.tar.gz/StShared/StConfigImpl.cpp -> sview-20_08.tar.gz/StShared/StConfigImpl.cpp Changed
19
 
1
@@ -134,7 +134,7 @@
2
     } catch(ParseException& ex) {
3
         ST_DEBUG_LOG("StSettings, error on line " + ex.getLine() + ": " + ex.getError());
4
         return false;
5
-    } catch(SettingNotFoundException nfex) {
6
+    } catch(SettingNotFoundException& nfex) {
7
         ST_DEBUG_LOG("StSettings, setting not found: " + nfex.getPath());
8
         return false;
9
     } catch(ConfigException& cex) {
10
@@ -189,7 +189,7 @@
11
     } catch(ParseException& ex) {
12
         ST_DEBUG_LOG("StSettings, error on line " + ex.getLine() + ": " + ex.getError());
13
         return false;
14
-    } catch(SettingNotFoundException nfex) {
15
+    } catch(SettingNotFoundException& nfex) {
16
         ST_DEBUG_LOG("StSettings, setting not found: " + nfex.getPath());
17
         return false;
18
     } catch(ConfigException& cex) {
19
sview-17_04.tar.gz/StShared/StDevILImage.cpp -> sview-20_08.tar.gz/StShared/StDevILImage.cpp Changed
17
 
1
@@ -51,6 +51,7 @@
2
 #define IL_PNG          0x042A
3
 #define IL_PSD          0x0439
4
 #define IL_HDR          0x043F
5
+#define IL_DDS          0x0437
6
 
7
 // Matches OpenGL's right now.
8
 #define IL_RGB              0x1907
9
@@ -235,6 +236,7 @@
10
             case StImageFile::ST_TYPE_JPS:  return IL_JPG;
11
             case StImageFile::ST_TYPE_PSD:  return IL_PSD;
12
             case StImageFile::ST_TYPE_HDR:  return IL_HDR;
13
+            case StImageFile::ST_TYPE_DDS:  return IL_DDS;
14
             case StImageFile::ST_TYPE_NONE:
15
             default:
16
                 return IL_TYPE_UNKNOWN;
17
sview-17_04.tar.gz/StShared/StExifDir.cpp -> sview-20_08.tar.gz/StShared/StExifDir.cpp Changed
25
 
1
@@ -249,7 +249,12 @@
2
                         }
3
                     }
4
                 } else {
5
-                    ST_DEBUG_LOG("StExifDir, found unsupported (" + CameraMaker + ") maker notes");
6
+                    if(anEntry.Format == StExifEntry::FMT_STRING) {
7
+                        StString aMakerNoteName((char *)anEntry.ValuePtr);
8
+                        ST_DEBUG_LOG("StExifDir, found unsupported (" + aMakerNoteName + ") maker notes");
9
+                    } else {
10
+                        ST_DEBUG_LOG("StExifDir, found unsupported (" + CameraMaker + ": " + CameraModel + ") maker notes");
11
+                    }
12
                 }
13
                 break;
14
             }
15
@@ -474,7 +479,8 @@
16
         if(aDir->Type == theQuery.Type) {
17
             for(size_t anEntryId = 0; anEntryId < aDir->Entries.size(); ++anEntryId) {
18
                 const StExifEntry& anEntry = aDir->Entries[anEntryId];
19
-                if(anEntry.Tag == theQuery.Entry.Tag) {
20
+                if(anEntry.Tag == theQuery.Entry.Tag
21
+                && (anEntry.Format == theQuery.Entry.Format || theQuery.Entry.Format == 0)) {
22
                     theQuery.Entry  = anEntry;
23
                     theQuery.Folder = aDir.access();
24
                     return true;
25
sview-17_04.tar.gz/StShared/StFTFont.cpp -> sview-20_08.tar.gz/StShared/StFTFont.cpp Changed
193
 
1
@@ -24,6 +24,7 @@
2
     }
3
     stMemZero(mySubsets, sizeof(mySubsets));
4
     stMemZero(myFTFaces, sizeof(myFTFaces));
5
+    stMemZero(myFontFaces, sizeof(myFontFaces));
6
 }
7
 
8
 StFTFont::~StFTFont() {
9
@@ -43,6 +44,7 @@
10
             aFace = NULL;
11
         }
12
         myFontPaths[aStyleIt].clear();
13
+        myFontFaces[aStyleIt] = 0;
14
     }
15
 }
16
 
17
@@ -52,6 +54,7 @@
18
     }
19
 
20
     if(myFTFaces[theStyle] != NULL) {
21
+        myUChar  = 0;
22
         myStyle  = theStyle;
23
         myFTFace = myFTFaces[theStyle];
24
         return true;
25
@@ -102,8 +105,10 @@
26
     return true;
27
 }
28
 
29
-bool StFTFont::load(const StString&       theFontPath,
30
-                    const StFTFont::Style theStyle) {
31
+bool StFTFont::load(const StString& theFontPath,
32
+                    const int theFaceId,
33
+                    const StFTFont::Style theStyle,
34
+                    const bool theToSyntItalic) {
35
     if(!myFTLib->isValid()
36
     || theStyle <  Style_Regular
37
     || theStyle >= StylesNB
38
@@ -114,18 +119,34 @@
39
     myFTFace = NULL;
40
     myGlyphImg.nullify();
41
     myFontPaths[theStyle] = theFontPath;
42
+    myFontFaces[theStyle] = theFaceId;
43
 
44
     FT_Face& aFace = myFTFaces[theStyle];
45
     if(aFace != NULL) {
46
         FT_Done_Face(aFace);
47
     }
48
     const StString aFontPath = StFileNode::getCompatibleName(theFontPath);
49
-    if(FT_New_Face(myFTLib->getInstance(), aFontPath.toCString(), 0, &aFace) != 0) {
50
+    if(FT_New_Face(myFTLib->getInstance(), aFontPath.toCString(), (FT_Long )theFaceId, &aFace) != 0) {
51
         ST_DEBUG_LOG("Font '" + aFontPath + "' fail to load!");
52
         FT_Done_Face(aFace);
53
         aFace = NULL;
54
         return false;
55
     }
56
+
57
+    if(theToSyntItalic) {
58
+        const double THE_SHEAR_ANGLE = 10.0 * M_PI / 180.0;
59
+
60
+        FT_Matrix aMat;
61
+        aMat.xx = FT_Fixed(std::cos(-THE_SHEAR_ANGLE) * (1 << 16));
62
+        aMat.xy = 0;
63
+        aMat.yx = 0;
64
+        aMat.yy = aMat.xx;
65
+
66
+        FT_Fixed aFactor = FT_Fixed(std::tan(THE_SHEAR_ANGLE) * (1 << 16));
67
+        aMat.xy += FT_MulFix(aFactor, aMat.xx);
68
+
69
+        FT_Set_Transform(aFace, &aMat, 0);
70
+    }
71
     return loadCharmap(aFontPath, aFace);
72
 }
73
 
74
@@ -144,6 +165,7 @@
75
     myFTFace = NULL;
76
     myGlyphImg.nullify();
77
     myFontPaths[theStyle] = theFontName;
78
+    myFontFaces[theStyle] = 0;
79
 
80
     FT_Face& aFace = myFTFaces[theStyle];
81
     if(aFace != NULL) {
82
@@ -171,13 +193,11 @@
83
 
84
     // test Unicode subsets
85
     mySubsets[Subset_General] = true;
86
-    mySubsets[Subset_Korean]  = FT_Get_Char_Index(theFace, 0x0B371) != 0
87
-                             && FT_Get_Char_Index(theFace, 0x0D130) != 0;
88
-    mySubsets[Subset_CJK]     = FT_Get_Char_Index(theFace, 0x06F22) != 0;
89
-
90
-//if(mySubsets[Subset_Korean]) { std::cerr << "  found Korean in " << myFontPath << "\n"; }
91
-//if(mySubsets[Subset_CJK])    { std::cerr << "  found CJK    in " << myFontPath << "\n"; }
92
-
93
+    mySubsets[Subset_Korean]  =     FT_Get_Char_Index(theFace, 0x0B371) != 0
94
+                                 && FT_Get_Char_Index(theFace, 0x0D130) != 0;
95
+    mySubsets[Subset_CJK]         = FT_Get_Char_Index(theFace, 0x06F22) != 0;
96
+    mySubsets[Subset_Arabic]      = FT_Get_Char_Index(theFace, 0x00600) != 0;
97
+    mySubsets[Subset_MiscSymbols] = FT_Get_Char_Index(theFace, 0x0266A) != 0;
98
     return true;
99
 }
100
 
101
@@ -294,56 +314,65 @@
102
     addAdvanceY(theUCharNext, thePen);
103
 }
104
 
105
-float StFTFont::getAdvanceX(const stUtf32_t theUCharNext) {
106
+bool StFTFont::getKerning(FT_Vector&      theKern,
107
+                          const stUtf32_t theUCharCurr,
108
+                          const stUtf32_t theUCharNext) const {
109
+    theKern.x = 0;
110
+    theKern.y = 0;
111
+    if(theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0) {
112
+        const FT_UInt aCharCurr = FT_Get_Char_Index(myFTFace, theUCharCurr);
113
+        const FT_UInt aCharNext = FT_Get_Char_Index(myFTFace, theUCharNext);
114
+        if(aCharCurr == 0 || aCharNext == 0
115
+        || FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0) {
116
+            theKern.x = 0;
117
+            theKern.y = 0;
118
+            return false;
119
+        }
120
+        return true;
121
+    }
122
+    return false;
123
+}
124
+
125
+float StFTFont::getAdvanceX(const stUtf32_t theUCharNext) const {
126
     if(myUChar == 0) {
127
         return 0.0f;
128
     }
129
 
130
-    if(FT_HAS_KERNING(myFTFace) == 0 || theUCharNext == 0
131
-    || FT_Get_Kerning(myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) {
132
-        return float(myFTFace->glyph->advance.x) / 64.0f;
133
-    }
134
-    return float(myKernAdvance.x + myFTFace->glyph->advance.x) / 64.0f;
135
+    FT_Vector aKern;
136
+    getKerning(aKern, myUChar, theUCharNext);
137
+    return float(aKern.x + myFTFace->glyph->advance.x) / 64.0f;
138
 }
139
 
140
-float StFTFont::getAdvanceY(const stUtf32_t theUCharNext) {
141
+float StFTFont::getAdvanceY(const stUtf32_t theUCharNext) const {
142
     if(myUChar == 0) {
143
         return 0.0f;
144
     }
145
 
146
-    if(FT_HAS_KERNING(myFTFace) == 0 || theUCharNext == 0
147
-    || FT_Get_Kerning(myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) {
148
-        return float(myFTFace->glyph->advance.y) / 64.0f;
149
-    }
150
-    return float(myKernAdvance.y + myFTFace->glyph->advance.y) / 64.0f;
151
+    FT_Vector aKern;
152
+    getKerning(aKern, myUChar, theUCharNext);
153
+    return float(aKern.y + myFTFace->glyph->advance.y) / 64.0f;
154
 }
155
 
156
 void StFTFont::addAdvanceX(const stUtf32_t  theUCharNext,
157
-                           StVec2<GLfloat>& thePen) {
158
+                           StVec2<GLfloat>& thePen) const {
159
     if(myUChar == 0) {
160
         return;
161
     }
162
 
163
-    if(FT_HAS_KERNING(myFTFace) == 0 || theUCharNext == 0
164
-    || FT_Get_Kerning(myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) {
165
-        thePen.x() += float(myFTFace->glyph->advance.x) / 64.0f;
166
-    } else {
167
-        thePen.x() += float(myKernAdvance.x + myFTFace->glyph->advance.x) / 64.0f;
168
-    }
169
+    FT_Vector aKern;
170
+    getKerning(aKern, myUChar, theUCharNext);
171
+    thePen.x() += float(aKern.x + myFTFace->glyph->advance.x) / 64.0f;
172
 }
173
 
174
 void StFTFont::addAdvanceY(const stUtf32_t  theUCharNext,
175
-                           StVec2<GLfloat>& thePen) {
176
+                           StVec2<GLfloat>& thePen) const {
177
     if(myUChar == 0) {
178
         return;
179
     }
180
 
181
-    if(FT_HAS_KERNING(myFTFace) == 0 || theUCharNext == 0
182
-    || FT_Get_Kerning(myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) {
183
-        thePen.y() += float(myFTFace->glyph->advance.y) / 64.0f;
184
-    } else {
185
-        thePen.y() += float(myKernAdvance.y + myFTFace->glyph->advance.y) / 64.0f;
186
-    }
187
+    FT_Vector aKern;
188
+    getKerning(aKern, myUChar, theUCharNext);
189
+    thePen.y() += float(aKern.y + myFTFace->glyph->advance.y) / 64.0f;
190
 }
191
 
192
 bool StFTFont::hasSymbol(const stUtf32_t theUChar) const {
193
sview-17_04.tar.gz/StShared/StFTFontRegistry.cpp -> sview-20_08.tar.gz/StShared/StFTFontRegistry.cpp Changed
331
 
1
@@ -13,9 +13,14 @@
2
 #include <StThreads/StProcess.h>
3
 #include <stAssert.h>
4
 
5
+#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
6
+  // use fontconfig library on Linux
7
+  #include <fontconfig/fontconfig.h>
8
+#endif
9
+
10
 namespace {
11
-    const StFTFontFamily THE_NO_FAMILY;
12
-};
13
+    static const StFTFontFamily THE_NO_FAMILY;
14
+}
15
 
16
 StFTFontRegistry::StFTFontRegistry() {
17
     myFTLib = new StFTLibrary();
18
@@ -51,7 +56,8 @@
19
     myFolders.add(stCString("/Library/Fonts"));
20
 
21
     // western
22
-    myFilesMajor.add(stCString("Times.dfont"));
23
+    myFilesMinor.add(stCString("Times.dfont")); // old macOS
24
+    myFilesMajor.add(stCString("Times.ttc"));
25
     myFilesMajor.add(stCString("Times New Roman.ttf"));
26
     myFilesMajor.add(stCString("Times New Roman Bold.ttf"));
27
     myFilesMajor.add(stCString("Times New Roman Italic.ttf"));
28
@@ -67,7 +73,8 @@
29
     //myFilesMajor.add(stCString("AppleMyungjo.ttf"));
30
     myFilesMajor.add(stCString("AppleGothic.ttf"));
31
     // chinese
32
-    myFilesMajor.add(stCString("华文仿宋.ttf"));
33
+    myFilesMinor.add(stCString("华文仿宋.ttf")); // old macOS
34
+    myFilesMajor.add(stCString("Songti.ttc"));
35
 #elif defined(__ANDROID__)
36
     myFolders.add(stCString("/system/fonts"));
37
 
38
@@ -90,6 +97,7 @@
39
     myFilesMajor.add(stCString("DroidSansMono.ttf"));
40
 
41
     // not all phones have the following fonts
42
+    myFilesMinor.add(stCString("NotoSansCJK-Regular.ttc"));
43
 
44
     // Korean
45
     myFilesMinor.add(stCString("NanumGothic.ttf"));
46
@@ -104,9 +112,32 @@
47
 
48
     // Japanese
49
     //myFilesMinor.add(stCString("NotoSansJP-Regular.otf"));
50
+
51
+    // Arabic
52
+    myFilesMinor.add(stCString("NotoNaskhArabic-Regular.ttf"));
53
+    //myFilesMinor.add(stCString("NotoNaskhArabic-Bold.ttf"));
54
 #else
55
-    myFolders.add(stCString("/usr/share/fonts"));
56
-    myFolders.add(stCString("/usr/local/share/fonts"));
57
+
58
+#if !defined(__EMSCRIPTEN__)
59
+    if(FcConfig* aFcCfg = FcInitLoadConfig()) {
60
+        if(FcStrList* aFcFontDir = FcConfigGetFontDirs(aFcCfg)) {
61
+            for(;;) {
62
+                FcChar8* aFcFolder = FcStrListNext(aFcFontDir);
63
+                if(aFcFolder == NULL) {
64
+                    break;
65
+                }
66
+
67
+                myFolders.add(StString((const char* )aFcFolder));
68
+            }
69
+            FcStrListDone(aFcFontDir);
70
+        }
71
+        FcConfigDestroy(aFcCfg);
72
+    }
73
+#endif
74
+    if(myFolders.isEmpty()) {
75
+        myFolders.add(stCString("/usr/share/fonts"));
76
+        myFolders.add(stCString("/usr/local/share/fonts"));
77
+    }
78
 
79
     // western
80
     myFilesMajor.add(stCString("DejaVuSerif.ttf"));
81
@@ -130,6 +161,7 @@
82
     myFilesMajor.add(stCString("NanumMyeongjoBold.ttf"));
83
     myFilesMajor.add(stCString("NanumGothic.ttf"));
84
     myFilesMajor.add(stCString("NanumGothicBold.ttf"));
85
+    myFilesMinor.add(stCString("NotoSerifCJK-Regular.ttc"));
86
 
87
     // chinese
88
     //myFilesMajor.add(stCString("DroidSansJapanese.ttf"));
89
@@ -145,6 +177,98 @@
90
     myFolders.add(theFolder);
91
 }
92
 
93
+bool StFTFontRegistry::registerFamily(const StString& theFontPath, int theFaceId) {
94
+    const FT_Long aFaceId = theFaceId != -1 ? theFaceId : 0;
95
+    FT_Face aFace = NULL;
96
+    if(FT_New_Face(myFTLib->getInstance(), theFontPath.toCString(), aFaceId, &aFace) != 0) {
97
+        if(aFace != NULL) {
98
+            FT_Done_Face(aFace);
99
+        }
100
+        return false;
101
+    }
102
+    if(aFace->family_name == NULL // skip broken fonts (error in FreeType?)
103
+    || FT_Select_Charmap(aFace, ft_encoding_unicode) != 0) { // handle only UNICODE fonts
104
+        FT_Done_Face(aFace);
105
+        return false;
106
+    }
107
+
108
+    // generate font family name
109
+    StString aStyle(aFace->style_name != NULL ? aFace->style_name : "");
110
+    {
111
+        // remove standard style combinations reflected by style_flags
112
+        // and keep only extra styles like Light, Condensed and similar
113
+        static const StString THE_EMPTY;
114
+        static const StString THE_SPACE1(" ");
115
+        static const StString THE_SPACE2("  ");
116
+        static const StString THE_ITALIC1("Italic");
117
+        static const StString THE_ITALIC2("Oblique");
118
+        static const StString THE_BOLD("Bold");
119
+        static const StString THE_REGULAR1("Regular");
120
+        static const StString THE_REGULAR2("Book");
121
+        if(aFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
122
+            aStyle = aStyle.replace(THE_BOLD, THE_EMPTY);
123
+            const size_t aLen = aStyle.Length;
124
+            aStyle = aStyle.replace(THE_ITALIC1, THE_EMPTY);
125
+            if(aLen == aStyle.Length) {
126
+                aStyle = aStyle.replace(THE_ITALIC2, THE_EMPTY);
127
+            }
128
+        } else if(aFace->style_flags == FT_STYLE_FLAG_BOLD) {
129
+            aStyle = aStyle.replace(THE_BOLD, THE_EMPTY);
130
+        } else if(aFace->style_flags == FT_STYLE_FLAG_ITALIC) {
131
+            const size_t aLen = aStyle.Length;
132
+            aStyle = aStyle.replace(THE_ITALIC1, THE_EMPTY);
133
+            if(aLen == aStyle.Length) {
134
+                aStyle = aStyle.replace(THE_ITALIC2, THE_EMPTY);
135
+            }
136
+        }
137
+        const size_t aLen2 = aStyle.Length;
138
+        aStyle = aStyle.replace(THE_REGULAR1, THE_EMPTY);
139
+        if(aLen2 == aStyle.Length) {
140
+            aStyle = aStyle.replace(THE_REGULAR2, THE_EMPTY);
141
+        }
142
+        aStyle.leftAdjust();
143
+        aStyle.rightAdjust();
144
+        aStyle.replace(THE_SPACE2, THE_SPACE1);
145
+    }
146
+
147
+    StString aFamilyName = aFace->family_name;
148
+    if(!aStyle.isEmpty()) {
149
+        aFamilyName = aFamilyName + " " + aStyle;
150
+    }
151
+
152
+    StFTFontFamily& aFamily = myFonts[aFamilyName];
153
+    aFamily.FamilyName = aFamilyName;
154
+    if(aFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
155
+        aFamily.BoldItalic = theFontPath;
156
+        aFamily.BoldItalicFace = (int )aFaceId;
157
+    } else if(aFace->style_flags == FT_STYLE_FLAG_BOLD) {
158
+        aFamily.Bold = theFontPath;
159
+        aFamily.BoldFace = (int )aFaceId;
160
+    } else if(aFace->style_flags == FT_STYLE_FLAG_ITALIC) {
161
+        aFamily.Italic = theFontPath;
162
+        aFamily.ItalicFace = (int )aFaceId;
163
+    } else {
164
+        aFamily.Regular = theFontPath;
165
+        aFamily.RegularFace = (int )aFaceId;
166
+    }
167
+    //ST_DEBUG_LOG("StFTFontRegistry, font file '" + theFontPath + " [" + aFaceId + "]" + "', family '" + aFamily.FamilyName + "', contains " + aFace->num_glyphs + " glyphs!");
168
+
169
+    if(theFaceId < aFace->num_faces) {
170
+        const FT_Long aNbInstances = aFace->style_flags >> 16;
171
+        for(FT_Long anInstIter = 1; anInstIter < aNbInstances; ++anInstIter) {
172
+            const FT_Long aSubFaceId = aFaceId + (anInstIter << 16);
173
+            registerFamily(theFontPath, aSubFaceId);
174
+        }
175
+    }
176
+    if(theFaceId == -1) {
177
+        for(FT_Long aFaceIter = 1; aFaceIter < aFace->num_faces; ++aFaceIter) {
178
+            registerFamily(theFontPath, aFaceIter);
179
+        }
180
+    }
181
+    FT_Done_Face(aFace);
182
+    return true;
183
+}
184
+
185
 void StFTFontRegistry::searchFiles(const StArrayList<StString>& theNames,
186
                                    const bool                   theIsMajor) {
187
     for(size_t aNameIter = 0; aNameIter < theNames.size(); ++aNameIter) {
188
@@ -165,32 +289,13 @@
189
             continue;
190
         }
191
 
192
-        FT_Face aFace = NULL;
193
-        if(FT_New_Face(myFTLib->getInstance(), aPath.toCString(), 0, &aFace) != 0) {
194
+        if(!registerFamily(aPath, -1)) {
195
             if(theIsMajor) {
196
                 ST_ERROR_LOG("StFTFontRegistry, major font file '" + aName + "' fail to load"
197
                             + " from path '" + aPath + "'!");
198
             }
199
-            if(aFace != NULL) {
200
-                FT_Done_Face(aFace);
201
-            }
202
             continue;
203
         }
204
-
205
-        StFTFontFamily& aFamily = myFonts[aFace->family_name];
206
-        aFamily.FamilyName = aFace->family_name;
207
-        if(aFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) {
208
-            aFamily.BoldItalic = aPath;
209
-        } else if(aFace->style_flags == FT_STYLE_FLAG_BOLD) {
210
-            aFamily.Bold = aPath;
211
-        } else if(aFace->style_flags == FT_STYLE_FLAG_ITALIC) {
212
-            aFamily.Italic = aPath;
213
-        } else {
214
-            aFamily.Regular = aPath;
215
-        }
216
-        //ST_DEBUG_LOG("StFTFontRegistry, font file '" + aName + "', family '" + aFamily.FamilyName + "', contains " + aFace->num_glyphs + " glyphs!");
217
-
218
-        FT_Done_Face(aFace);
219
     }
220
 }
221
 
222
@@ -217,11 +322,16 @@
223
     aSerif.Western = findFont(stCString("Times New Roman"));
224
     aSans .Western = findFont(stCString("Trebuchet MS"));
225
     aMono .Western = findFont(stCString("Tahoma"));
226
+    aSans.MiscSymbols = aSerif.Western; // Trebuchet font does not include this sub-set
227
     const StFTFontFamily& aMalgun = findFont(stCString("Malgun Gothic"));
228
     const StFTFontFamily& aGulim  = findFont(stCString("Gulim"));
229
     const StFTFontFamily& aKor = aMalgun.FamilyName.isEmpty() && !aGulim.FamilyName.isEmpty()
230
                                ? aGulim
231
                                : aMalgun;
232
+    const StFTFontFamily& anArabic = findFont(stCString("Times New Roman"));
233
+    aSerif.Arabic  = anArabic;
234
+    aSans .Arabic  = anArabic;
235
+    aMono .Arabic  = anArabic;
236
     aSerif.Korean  = aKor;
237
     aSans .Korean  = aKor;
238
     aMono .Korean  = aKor;
239
@@ -236,9 +346,17 @@
240
     aSerif.Korean  = findFont(stCString("AppleGothic")); // AppleMyungjo can not be loaded
241
     aSans .Korean  = findFont(stCString("AppleGothic"));
242
     aMono .Korean  = findFont(stCString("AppleGothic"));
243
-    aSerif.CJK     = findFont(stCString("STFangsong"));
244
-    aSans .CJK     = findFont(stCString("STFangsong"));
245
-    aMono .CJK     = findFont(stCString("STFangsong"));
246
+    const StFTFontFamily& aSongtiSC = findFont(stCString("Songti SC Light"));
247
+    const StFTFontFamily& aFang = findFont(stCString("STFangsong"));
248
+    const StFTFontFamily& aCjk = aSongtiSC.FamilyName.isEmpty() && !aFang.FamilyName.isEmpty()
249
+                               ? aFang
250
+                               : aSongtiSC;
251
+    aSerif.CJK     = aCjk;
252
+    aSans .CJK     = aCjk;
253
+    aMono .CJK     = aCjk;
254
+    aSerif.Arabic  = findFont(stCString("DecoType Naskh"));
255
+    aSans .Arabic  = findFont(stCString("DecoType Naskh"));
256
+    aMono .Arabic  = findFont(stCString("DecoType Naskh"));
257
 #elif defined(__ANDROID__)
258
     aSerif.Western = findFont(stCString("Noto Serif"));
259
     if(aSerif.Western.FamilyName.isEmpty()) {
260
@@ -246,21 +364,41 @@
261
     }
262
     aSans .Western = findFont(stCString("Roboto")); // actually DroidSans.ttf
263
     aMono .Western = findFont(stCString("Droid Sans Mono"));
264
+
265
     aSerif.Korean  = findFont(stCString("NanumGothic")); // no serif
266
-    aSans .Korean  = findFont(stCString("NanumGothic"));
267
-    aMono .Korean  = findFont(stCString("NanumGothic"));
268
+    aSans .Korean  = aSerif.Korean;
269
+    aMono .Korean  = aSerif.Korean;
270
     if(aSerif.Korean.FamilyName.isEmpty()) {
271
         aSerif.Korean = findFont(stCString("Noto Sans KR"));
272
-        aSans .Korean = findFont(stCString("Noto Sans KR"));
273
-        aMono .Korean = findFont(stCString("Noto Sans KR"));
274
+        aSans .Korean = aSerif.Korean;
275
+        aMono .Korean = aSerif.Korean;
276
     }
277
     aSerif.CJK     = findFont(stCString("Droid Sans Fallback"));
278
-    aSans .CJK     = findFont(stCString("Droid Sans Fallback"));
279
-    aMono .CJK     = findFont(stCString("Droid Sans Fallback"));
280
+    aSans .CJK     = aSerif.CJK;
281
+    aMono .CJK     = aSerif.CJK;
282
     if(aSerif.CJK.FamilyName.isEmpty()) {
283
         aSerif.CJK = findFont(stCString("Noto Sans SC"));
284
-        aSans .CJK = findFont(stCString("Noto Sans SC"));
285
-        aMono .CJK = findFont(stCString("Noto Sans SC"));
286
+        aSans .CJK = aSerif.CJK;
287
+        aMono .CJK = aSerif.CJK;
288
+    }
289
+    if(aSerif.CJK.FamilyName.isEmpty()) {
290
+        aSerif.CJK = findFont(stCString("Noto Sans CJK JP"));
291
+        aSans .CJK = aSerif.CJK;
292
+        aMono .CJK = aSerif.CJK;
293
+    }
294
+    if(aSerif.Korean.FamilyName.isEmpty()) {
295
+        aSerif.Korean = aSerif.CJK;
296
+        aSans .Korean = aSerif.CJK;
297
+        aMono .Korean = aSerif.CJK;
298
+    }
299
+
300
+    aSerif.Arabic = findFont(stCString("Droid Arabic Naskh"));
301
+    aSans .Arabic = aSerif.Arabic;
302
+    aMono .Arabic = aSerif.Arabic;
303
+    if(aSerif.Arabic.FamilyName.isEmpty()) {
304
+        aSerif.Arabic = findFont(stCString("Noto Naskh Arabic"));
305
+        aSans .Arabic = aSerif.Arabic;
306
+        aMono .Arabic = aSerif.Arabic;
307
     }
308
 #else
309
     aSerif.Western = findFont(stCString("FreeSerif"));
310
@@ -270,9 +408,17 @@
311
         aSans .Western = findFont(stCString("DejaVu Sans"));
312
     }
313
     aMono .Western = findFont(stCString("DejaVu Sans Mono"));
314
-    aSerif.Korean  = findFont(stCString("NanumMyeongjo"));
315
-    aSans .Korean  = findFont(stCString("NanumGothic"));
316
-    aMono .Korean  = findFont(stCString("NanumGothic"));
317
+
318
+    const StFTFontFamily& aNanumMyeon     = findFont(stCString("NanumMyeongjo"));
319
+    const StFTFontFamily& aNotoSerifCjkJp = findFont(stCString("Noto Serif CJK JP"));
320
+    const StFTFontFamily& aNanumGoth      = findFont(stCString("NanumGothic"));
321
+    aSerif.Korean  = aNanumMyeon.FamilyName.isEmpty() && !aNotoSerifCjkJp.FamilyName.isEmpty()
322
+                   ? aNotoSerifCjkJp
323
+                   : aNanumMyeon;;
324
+    aSans .Korean  = aNanumGoth.FamilyName.isEmpty() && !aNotoSerifCjkJp.FamilyName.isEmpty()
325
+                   ? aNotoSerifCjkJp
326
+                   : aNanumGoth;
327
+    aMono .Korean  = aSans.Korean;
328
     aSerif.CJK     = findFont(stCString("Droid Sans Fallback"));
329
     aSans .CJK     = findFont(stCString("Droid Sans Fallback"));
330
     aMono .CJK     = findFont(stCString("Droid Sans Fallback"));
331
sview-17_04.tar.gz/StShared/StFileNode.ObjC.mm -> sview-20_08.tar.gz/StShared/StFileNode.ObjC.mm Changed
66
 
1
@@ -9,7 +9,6 @@
2
 #if (defined(__APPLE__))
3
 
4
 #include <StFile/StFileNode.h>
5
-#include <StFile/StMIMEList.h>
6
 
7
 #include <StCocoa/StCocoaLocalPool.h>
8
 
9
@@ -68,21 +67,21 @@
10
             [aFilePanel setAllowedFileTypes: myFilter];
11
         }
12
 
13
+    ST_DISABLE_DEPRECATION_WARNINGS
14
         if([aFilePanel runModal] == NSOKButton) {
15
             myIsFileSelected = true;
16
             // automatically convert filenames from decomposed form used by Mac OS X file systems
17
             NSString* aFileName = [[aFilePanel filename] precomposedStringWithCanonicalMapping];
18
             myResult = [aFileName UTF8String];
19
         }
20
+    ST_ENABLE_DEPRECATION_WARNINGS
21
     }
22
 
23
 @end
24
 
25
-bool StFileNode::openFileDialog(const StString& theFolder,
26
-                                const StString& theTitle,
27
-                                const StMIMEList& theFilter,
28
-                                StString& theFilePath,
29
-                                bool toSave) {
30
+bool StFileNode::openFileDialog(StString& theFilePath,
31
+                                const StOpenFileName& theInfo,
32
+                                bool theToSave) {
33
     if(NSApp == nil) {
34
         return false;
35
     }
36
@@ -91,14 +90,14 @@
37
     StFileNode::getFolderAndFile(theFilePath, aFolderSrc, aFileNameSrc);
38
 
39
     StCocoaLocalPool aLocalPool;
40
-    NSString* aTitle     = [NSString stringWithUTF8String: theTitle.toCString()];
41
-    NSString* aFolder    = [NSString stringWithUTF8String: theFolder.toCString()];
42
+    NSString* aTitle     = [NSString stringWithUTF8String: theInfo.Title.toCString()];
43
+    NSString* aFolder    = [NSString stringWithUTF8String: theInfo.Folder.toCString()];
44
     NSString* anInitFile = [NSString stringWithUTF8String: aFileNameSrc.toCString()];
45
     NSMutableArray* aFilter = NULL;
46
-    if(!theFilter.isEmpty()) {
47
-        aFilter = [NSMutableArray arrayWithCapacity: theFilter.size()];
48
-        for(size_t aMimeId = 0; aMimeId < theFilter.size(); ++aMimeId) {
49
-            const StMIME& aMime = theFilter[aMimeId];
50
+    if(!theInfo.Filter.isEmpty()) {
51
+        aFilter = [NSMutableArray arrayWithCapacity: theInfo.Filter.size()];
52
+        for(size_t aMimeId = 0; aMimeId < theInfo.Filter.size(); ++aMimeId) {
53
+            const StMIME& aMime = theInfo.Filter[aMimeId];
54
             [aFilter addObject: [NSString stringWithUTF8String: aMime.getExtension().toCString()]];
55
         }
56
     }
57
@@ -107,7 +106,7 @@
58
                                                     withTitle: aTitle
59
                                                    withFolder: aFolder
60
                                                      withFile: anInitFile
61
-                                                       toSave: toSave];
62
+                                                       toSave: theToSave];
63
     if([NSThread isMainThread]) {
64
         [anOpenFile doDialog: NULL];
65
     } else {
66
sview-17_04.tar.gz/StShared/StFileNode.cpp -> sview-20_08.tar.gz/StShared/StFileNode.cpp Changed
46
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -81,6 +81,37 @@
9
 #endif
10
 }
11
 
12
+bool StFileNode::isFileReadOnly(const StCString& thePath) {
13
+#ifdef _WIN32
14
+    StStringUtfWide aPath;
15
+    aPath.fromUnicode(thePath);
16
+    DWORD anAttribs = ::GetFileAttributesW(aPath.toCString());
17
+    return (anAttribs & FILE_ATTRIBUTE_READONLY) != 0;
18
+#else
19
+    // not implemented
20
+    return false;
21
+#endif
22
+}
23
+
24
+bool StFileNode::removeReadOnlyFlag(const StCString& thePath) {
25
+#ifdef _WIN32
26
+    StStringUtfWide aPath;
27
+    aPath.fromUnicode(thePath);
28
+    DWORD anAttribs = ::GetFileAttributesW(aPath.toCString());
29
+    if(anAttribs == INVALID_FILE_ATTRIBUTES) {
30
+        return false;
31
+    } else if((anAttribs & FILE_ATTRIBUTE_READONLY) == 0) {
32
+        return true;
33
+    }
34
+
35
+    anAttribs = (anAttribs & ~FILE_ATTRIBUTE_READONLY);
36
+    return ::SetFileAttributesW(aPath.toCString(), anAttribs) != FALSE;
37
+#else
38
+    // not implemented
39
+    return false;
40
+#endif
41
+}
42
+
43
 bool StFileNode::removeFile(const StCString& thePath) {
44
 #ifdef _WIN32
45
     StStringUtfWide aPath;
46
sview-17_04.tar.gz/StShared/StFileNode2.cpp -> sview-20_08.tar.gz/StShared/StFileNode2.cpp Changed
126
 
1
@@ -9,7 +9,6 @@
2
 #ifndef __APPLE__
3
 
4
 #include <StFile/StFileNode.h>
5
-#include <StFile/StMIMEList.h>
6
 #include <StStrings/StLogger.h>
7
 
8
 #ifdef _WIN32
9
@@ -29,23 +28,20 @@
10
  * in commonly used class.
11
  * This needed only for Windows.
12
  */
13
-bool StFileNode::openFileDialog(const StString& theFolder,
14
-                                const StString& theTitle,
15
-                                const StMIMEList& theFilter,
16
-                                StString& theFilePath,
17
-                                bool toSave) {
18
+bool StFileNode::openFileDialog(StString& theFilePath,
19
+                                const StOpenFileName& theInfo,
20
+                                bool theToSave) {
21
 #ifdef _WIN32
22
-    const StStringUtfWide aFolder = theFolder.toUtfWide();
23
-    const StStringUtfWide aTitle  = theTitle.toUtfWide();
24
+    const StStringUtfWide aFolder = theInfo.Folder.toUtfWide();
25
+    const StStringUtfWide aTitle  = theInfo.Title.toUtfWide();
26
 
27
     // use dummy \n symbol instead of NULL-termination symbol \0 inside string
28
     // because such string will be invalid for StString class
29
     const StStringUtfWide NULL_CHAR = '\n';
30
 
31
-    StStringUtfWide aFilterString;
32
-    StStringUtfWide anAllSupportedExt;
33
-    for(size_t aMimeId = 0; aMimeId < theFilter.size(); ++aMimeId) {
34
-        const StMIME& aMime = theFilter[aMimeId];
35
+    StStringUtfWide aFilterString, anAllSupportedExt, anExtraSupportedExt;
36
+    for(size_t aMimeId = 0; aMimeId < theInfo.Filter.size(); ++aMimeId) {
37
+        const StMIME& aMime = theInfo.Filter[aMimeId];
38
         if(aMimeId > 0) {
39
             anAllSupportedExt += StStringUtfWide(';');
40
         }
41
@@ -53,15 +49,38 @@
42
     }
43
 
44
     // fill 'All supported'
45
-    if(!anAllSupportedExt.isEmpty() && theFilter.size() > 1) {
46
-        aFilterString += StStringUtfWide(L"All supported\n");
47
+    if(!anAllSupportedExt.isEmpty() && theInfo.Filter.size() > 1) {
48
+        if(!theInfo.FilterTitle.isEmpty()) {
49
+            aFilterString += theInfo.FilterTitle.toUtfWide();
50
+        } else {
51
+            aFilterString += StStringUtfWide(L"All supported");
52
+        }
53
+        aFilterString += StStringUtfWide(L"\n");
54
         aFilterString += anAllSupportedExt + NULL_CHAR;
55
     }
56
 
57
+    // fill 'Extra supported'
58
+    for(size_t aMimeId = 0; aMimeId < theInfo.ExtraFilter.size(); ++aMimeId) {
59
+        const StMIME& aMime = theInfo.ExtraFilter[aMimeId];
60
+        if(aMimeId > 0) {
61
+            anExtraSupportedExt += StStringUtfWide(';');
62
+        }
63
+        anExtraSupportedExt += StStringUtfWide(L"*.") + aMime.getExtension().toUtfWide();
64
+    }
65
+    if(!anExtraSupportedExt.isEmpty() && theInfo.ExtraFilter.size() > 1) {
66
+        if(!theInfo.ExtraFilterTitle.isEmpty()) {
67
+            aFilterString += theInfo.ExtraFilterTitle.toUtfWide();
68
+        } else {
69
+            aFilterString += StStringUtfWide(L"Extra supported");
70
+        }
71
+        aFilterString += StStringUtfWide(L"\n");
72
+        aFilterString += anExtraSupportedExt + NULL_CHAR;
73
+    }
74
+
75
     // fill MIME types
76
-    for(size_t aMimeId = 0; aMimeId < theFilter.size(); ++aMimeId) {
77
-        const StMIME& aMime = theFilter[aMimeId];
78
-        if((aMimeId > 0) && (aMime.getDescription() == theFilter[aMimeId - 1].getDescription())) {
79
+    for(size_t aMimeId = 0; aMimeId < theInfo.Filter.size(); ++aMimeId) {
80
+        const StMIME& aMime = theInfo.Filter[aMimeId];
81
+        if((aMimeId > 0) && (aMime.getDescription() == theInfo.Filter[aMimeId - 1].getDescription())) {
82
             // append extension to previous MIME (prevent duplication)
83
             aFilterString = aFilterString.subString(0, aFilterString.getLength() - 1); // backstep
84
             aFilterString += StStringUtfWide(L";*.") + aMime.getExtension().toUtfWide() + NULL_CHAR;
85
@@ -72,7 +91,7 @@
86
     }
87
 
88
     // fill 'Any File'
89
-    aFilterString += StStringUtfWide(L"Any File (*)\n");
90
+    aFilterString += StStringUtfWide(L"All Files (*)\n");
91
     aFilterString += StStringUtfWide(L"*\n"); // last string should be terminated by \0\0
92
 
93
     // replace dummy CR symbol within '\0' using 'hack' code
94
@@ -104,7 +123,7 @@
95
     anOpenStruct.nMaxFileTitle   = sizeof(aFileTitle);
96
     anOpenStruct.lpstrTitle      = aTitle.toCString();
97
     anOpenStruct.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
98
-    if(!toSave) {
99
+    if(!theToSave) {
100
         if(GetOpenFileNameW(&anOpenStruct)
101
         && *anOpenStruct.lpstrFile != L'\0') {
102
             theFilePath = StString(anOpenStruct.lpstrFile);
103
@@ -125,17 +144,17 @@
104
     }
105
     gdk_threads_enter();
106
     bool isFileSelected = false;
107
-    GtkWidget* aDialog = gtk_file_chooser_dialog_new(theTitle.toCString(), NULL, (toSave ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN),
108
-                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, (toSave ? GTK_STOCK_SAVE : GTK_STOCK_OPEN),
109
+    GtkWidget* aDialog = gtk_file_chooser_dialog_new(theInfo.Folder.toCString(), NULL, (theToSave ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN),
110
+                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, (theToSave ? GTK_STOCK_SAVE : GTK_STOCK_OPEN),
111
                                                      GTK_RESPONSE_ACCEPT, NULL);
112
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(aDialog), theFolder.toCString());
113
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(aDialog), theInfo.Folder.toCString());
114
     if(!theFilePath.isEmpty()) {
115
         gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(aDialog), theFilePath.toCString());
116
     }
117
 
118
     GtkFileFilter* gtkFilter = gtk_file_filter_new();
119
-    for(size_t aMimeId = 0; aMimeId < theFilter.size(); ++aMimeId) {
120
-        const StMIME& aMime = theFilter[aMimeId];
121
+    for(size_t aMimeId = 0; aMimeId < theInfo.Filter.size(); ++aMimeId) {
122
+        const StMIME& aMime = theInfo.Filter[aMimeId];
123
         gtk_file_filter_add_pattern(gtkFilter, (StString("*.") + aMime.getExtension()).toCString());
124
     }
125
 
126
sview-17_04.tar.gz/StShared/StFolder.cpp -> sview-20_08.tar.gz/StShared/StFolder.cpp Changed
24
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -54,12 +54,9 @@
9
     }
10
     return false;
11
 #else
12
-    DIR* aDir = opendir(thePath.toCString());
13
-    if(aDir == NULL) {
14
-        return false;
15
-    }
16
-    closedir(aDir);
17
-    return true;
18
+    struct stat aStatBuffer;
19
+    return stat(thePath.toCString(), &aStatBuffer) == 0
20
+        && S_ISDIR(aStatBuffer.st_mode);
21
 #endif
22
 }
23
 
24
sview-17_04.tar.gz/StShared/StFormatEnum.cpp -> sview-20_08.tar.gz/StShared/StFormatEnum.cpp Changed
18
 
1
@@ -70,6 +70,7 @@
2
 }
3
 
4
 StFormat st::formatFromName(const StString& theFileName,
5
+                            const bool      theToSwapJps,
6
                             bool&           theIsAnamorph) {
7
     StString aName, anExt;
8
     StFileNode::getNameAndExtension(theFileName, aName, anExt);
9
@@ -78,7 +79,7 @@
10
     if(anExt == stCString("pns")
11
     || anExt == stCString("jps")) {
12
         theIsAnamorph = false;
13
-        return StFormat_SideBySide_RL;
14
+        return theToSwapJps ? StFormat_SideBySide_LR : StFormat_SideBySide_RL;
15
     }
16
 
17
     // this is not optimized search, but should be OK for most use cases
18
sview-17_04.tar.gz/StShared/StFreeImage.cpp -> sview-20_08.tar.gz/StShared/StFreeImage.cpp Changed
9
 
1
@@ -302,6 +302,7 @@
2
         case StImageFile::ST_TYPE_JPS: return FIF_JPEG;
3
         case StImageFile::ST_TYPE_EXR: return FIF_EXR;
4
         case StImageFile::ST_TYPE_HDR: return FIF_HDR;
5
+        case StImageFile::ST_TYPE_DDS: return FIF_DDS;
6
         default: return FIF_UNKNOWN;
7
     }
8
 }
9
sview-17_04.tar.gz/StShared/StGLContext.cpp -> sview-20_08.tar.gz/StShared/StGLContext.cpp Changed
191
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2012-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2012-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -15,6 +15,7 @@
9
 
10
 #include <StGLCore/StGLCore44.h>
11
 #include <StGL/StGLArbFbo.h>
12
+#include <StGL/StGLTexture.h>
13
 
14
 #include <StStrings/StDictionary.h>
15
 #include <StStrings/StLogger.h>
16
@@ -51,27 +52,28 @@
17
   arbFbo(NULL),
18
   arbNPTW(false),
19
   arbTexRG(false),
20
+  arbTexFloat(false),
21
   arbTexClear(false),
22
 #if defined(GL_ES_VERSION_2_0)
23
-  hasUnpack(false),
24
   hasHighp(false),
25
   hasTexRGBA8(false),
26
   extTexBGRA8(false),
27
+  extTexR16(false),
28
 #else
29
-  hasUnpack(true),
30
   hasHighp(true),
31
   hasTexRGBA8(true), // always available on desktop
32
   extTexBGRA8(true),
33
+  extTexR16(true),
34
 #endif
35
   extAll(NULL),
36
   extSwapTear(false),
37
+  khrFlushControl(false),
38
   myFuncs(new StGLFunctions()),
39
   myResMgr(theResMgr),
40
   myGlVendor(GlVendor_UNKNOWN),
41
   myGpuName(GPU_UNKNOWN),
42
   myVerMajor(0),
43
   myVerMinor(0),
44
-  myMaxTexDim(0),
45
   myWasInit(false),
46
   myFramebufferDraw(0),
47
   myFramebufferRead(0),
48
@@ -84,6 +86,12 @@
49
 #ifdef __APPLE__
50
     mySysLib.loadSimple("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL");
51
 #endif
52
+
53
+#if defined(GL_ES_VERSION_2_0)
54
+    myDevCaps.hasUnpack = false;
55
+#else
56
+    myDevCaps.hasUnpack = true;
57
+#endif
58
 }
59
 
60
 StGLContext::StGLContext(const bool theToInitialize)
61
@@ -104,26 +112,27 @@
62
   arbFbo(NULL),
63
   arbNPTW(false),
64
   arbTexRG(false),
65
+  arbTexFloat(false),
66
   arbTexClear(false),
67
 #if defined(GL_ES_VERSION_2_0)
68
-  hasUnpack(false),
69
   hasHighp(false),
70
   hasTexRGBA8(false),
71
   extTexBGRA8(false),
72
+  extTexR16(false),
73
 #else
74
-  hasUnpack(true), // always available on desktop
75
   hasHighp(true),
76
   hasTexRGBA8(true),
77
   extTexBGRA8(true),
78
+  extTexR16(true),
79
 #endif
80
   extAll(NULL),
81
   extSwapTear(false),
82
+  khrFlushControl(false),
83
   myFuncs(new StGLFunctions()),
84
   myGlVendor(GlVendor_UNKNOWN),
85
   myGpuName(GPU_UNKNOWN),
86
   myVerMajor(0),
87
   myVerMinor(0),
88
-  myMaxTexDim(0),
89
   myWasInit(false),
90
   myFramebufferDraw(0),
91
   myFramebufferRead(0),
92
@@ -136,6 +145,12 @@
93
 #ifdef __APPLE__
94
     mySysLib.loadSimple("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL");
95
 #endif
96
+
97
+#if defined(GL_ES_VERSION_2_0)
98
+    myDevCaps.hasUnpack = false;
99
+#else
100
+    myDevCaps.hasUnpack = true; // always available on desktop
101
+#endif
102
     if(theToInitialize) {
103
         stglInit();
104
     }
105
@@ -460,7 +475,7 @@
106
     theMap.add(StDictEntry("GLdevice",    (const char* )glGetString(GL_RENDERER)));
107
     theMap.add(StDictEntry("GLversion",   (const char* )glGetString(GL_VERSION)));
108
     theMap.add(StDictEntry("GLSLversion", (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION)));
109
-    theMap.add(StDictEntry("Max texture size", myMaxTexDim));
110
+    theMap.add(StDictEntry("Max texture size", myDevCaps.maxTexDim));
111
     theMap.add(StDictEntry("Window Info", StString()
112
             + myViewport.width() + "x" + myViewport.height()
113
             + " RGB" + myWindowBits.RGB + " A" + myWindowBits.Alpha
114
@@ -669,8 +684,8 @@
115
     core11    = (StGLCore11*    )(&(*myFuncs));
116
     core11fwd = (StGLCore11Fwd* )(&(*myFuncs));
117
 
118
-    myMaxTexDim = 2048;
119
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
120
+    myDevCaps.maxTexDim = 2048;
121
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &myDevCaps.maxTexDim);
122
 
123
 #if !defined(GL_ES_VERSION_2_0)
124
     bool has12 = false;
125
@@ -694,7 +709,8 @@
126
 
127
     // retrieve platform-dependent extensions
128
 #if defined(ST_HAVE_EGL)
129
-    //const char* aEglExts = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
130
+    const char* anEglExts = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
131
+    khrFlushControl = stglCheckExtension(anEglExts, "EGL_KHR_context_flush_control");
132
 #elif defined(_WIN32)
133
     if(STGL_READ_FUNC(wglGetExtensionsStringARB)) {
134
         const char* aWglExts = myFuncs->wglGetExtensionsStringARB(wglGetCurrentDC());
135
@@ -708,6 +724,7 @@
136
         }
137
         if(stglCheckExtension(aWglExts, "WGL_ARB_create_context_profile")) {
138
             STGL_READ_FUNC(wglCreateContextAttribsARB);
139
+            khrFlushControl = stglCheckExtension(aWglExts, "WGL_ARB_context_flush_control");
140
         }
141
         extSwapTear = stglCheckExtension(aWglExts, "WGL_EXT_swap_control_tear");
142
         if(stglCheckExtension(aWglExts, "WGL_NV_DX_interop")) {
143
@@ -744,6 +761,7 @@
144
         STGL_READ_FUNC(glXQueryCurrentRendererStringMESA);
145
     }
146
     extSwapTear = stglCheckExtension(aGlxExts, "GLX_EXT_swap_control_tear");
147
+    khrFlushControl = stglCheckExtension(aGlxExts, "GLX_ARB_context_flush_control");
148
 #endif
149
 
150
 #if defined(GL_ES_VERSION_2_0)
151
@@ -754,11 +772,13 @@
152
     hasTexRGBA8 = isGlGreaterEqual(3, 0)
153
                || stglCheckExtension("GL_OES_rgb8_rgba8");
154
     extTexBGRA8 = stglCheckExtension("GL_EXT_texture_format_BGRA8888");
155
+    extTexR16   = stglCheckExtension("GL_EXT_texture_norm16");
156
     arbTexRG    = isGlGreaterEqual(3, 0)
157
                || stglCheckExtension("GL_EXT_texture_rg");
158
+    arbTexFloat = isGlGreaterEqual(3, 0);
159
     const bool hasFBO = isGlGreaterEqual(2, 0)
160
                      || stglCheckExtension("GL_OES_framebuffer_object");
161
-    hasUnpack = isGlGreaterEqual(3, 0);
162
+    myDevCaps.hasUnpack = isGlGreaterEqual(3, 0);
163
 
164
     if(isGlGreaterEqual(2, 0)) {
165
         // enable compatible functions
166
@@ -801,8 +821,11 @@
167
 #else
168
     hasTexRGBA8 = true;
169
     extTexBGRA8 = true;
170
+    extTexR16   = true;
171
     arbNPTW     = stglCheckExtension("GL_ARB_texture_non_power_of_two");
172
     arbTexRG    = stglCheckExtension("GL_ARB_texture_rg");
173
+    arbTexFloat = isGlGreaterEqual(3, 0)
174
+               || stglCheckExtension("GL_ARB_texture_float");
175
 
176
     // load OpenGL 1.2 new functions
177
     has12 = isGlGreaterEqual(1, 2)
178
@@ -1609,6 +1632,12 @@
179
         }*/
180
     }
181
 
182
+    for(int aFormatIter = 0; aFormatIter < StImagePlane::ImgNB; ++aFormatIter) {
183
+        const StImagePlane::ImgFormat aFormat = (StImagePlane::ImgFormat )aFormatIter;
184
+        GLint aDummy = 0;
185
+        myDevCaps.setSupportedFormat(aFormat, StGLTexture::getInternalFormat(*this, aFormat, aDummy));
186
+    }
187
+
188
     // log OpenGL info
189
     ST_DEBUG_LOG("Created new GL context:\n" + stglFullInfo());
190
 
191
sview-17_04.tar.gz/StShared/StGLFontManager.cpp -> sview-20_08.tar.gz/StShared/StGLFontManager.cpp Changed
35
 
1
@@ -67,10 +67,16 @@
2
     }
3
 
4
     StHandle<StFTFont> aFontFt = new StFTFont(myFTLib);
5
-    aFontFt->load(aFont.Regular,    StFTFont::Style_Regular);
6
-    aFontFt->load(aFont.Bold,       StFTFont::Style_Bold);
7
-    aFontFt->load(aFont.Italic,     StFTFont::Style_Italic);
8
-    aFontFt->load(aFont.BoldItalic, StFTFont::Style_BoldItalic);
9
+    const bool hasItalic     = !aFont.Italic.isEmpty();
10
+    const bool hasBoldItalic = !aFont.BoldItalic.isEmpty();
11
+    aFontFt->load(aFont.Regular, aFont.RegularFace,    StFTFont::Style_Regular);
12
+    aFontFt->load(aFont.Bold,    aFont.BoldFace,       StFTFont::Style_Bold);
13
+    aFontFt->load(hasItalic ? aFont.Italic : aFont.Regular,
14
+                  hasItalic ? aFont.ItalicFace : aFont.RegularFace,
15
+                  StFTFont::Style_Italic, !hasItalic);
16
+    aFontFt->load(hasBoldItalic ? aFont.BoldItalic : aFont.Bold,
17
+                  hasBoldItalic ? aFont.BoldItalicFace : aFont.BoldFace,
18
+                  StFTFont::Style_BoldItalic, !hasBoldItalic);
19
     aFontFt->init(theSize, myResolution);
20
     aFontGl = new StGLFontEntry(aFontFt);
21
     return aFontGl;
22
@@ -107,6 +113,12 @@
23
     aGenFont                                    = findCreate(aPack.Western.FamilyName, theSize);
24
     aFont->changeFont(StFTFont::Subset_CJK)     = findCreate(aPack.CJK    .FamilyName, theSize);
25
     aFont->changeFont(StFTFont::Subset_Korean)  = findCreate(aPack.Korean .FamilyName, theSize);
26
+    if(aGenFont.isNull() || !aGenFont->hasSubset(StFTFont::Subset_Arabic)) {
27
+        aFont->changeFont(StFTFont::Subset_Arabic) = findCreate(aPack.Arabic.FamilyName, theSize);
28
+    }
29
+    if(aGenFont.isNull() || !aGenFont->hasSubset(StFTFont::Subset_MiscSymbols)) {
30
+        aFont->changeFont(StFTFont::Subset_MiscSymbols) = findCreate(aPack.MiscSymbols.FamilyName, theSize);
31
+    }
32
 
33
     if(aGenFont.isNull()) {
34
         aGenFont = findCreateFallback(theSize);
35
sview-17_04.tar.gz/StShared/StGLProjCamera.cpp -> sview-20_08.tar.gz/StShared/StGLProjCamera.cpp Changed
134
 
1
@@ -18,6 +18,7 @@
2
 StGLProjCamera::StGLProjCamera()
3
 : myMatrix(),
4
   myMatrixMono(),
5
+  myIsCustomFrust(false),
6
   myFOVy(45.0f),
7
   myZoom(1.0f),
8
   myAspect(1.0f),
9
@@ -41,6 +42,7 @@
10
                                const GLfloat theZScreen)
11
 : myMatrix(),
12
   myMatrixMono(),
13
+  myIsCustomFrust(false),
14
   myFOVy(theFOVy),
15
   myZoom(1.0f),
16
   myAspect(1.0f),
17
@@ -58,6 +60,56 @@
18
     updateFrustum();
19
 }
20
 
21
+StGLProjCamera::StGLProjCamera(const StGLProjCamera& theOther)
22
+: myMatrix(theOther.myMatrix),
23
+  myMatrixMono(theOther.myMatrixMono),
24
+  myVrFrustumL(theOther.myVrFrustumL),
25
+  myVrFrustumR(theOther.myVrFrustumR),
26
+  myIsCustomFrust(theOther.myIsCustomFrust),
27
+  myFOVy(theOther.myFOVy),
28
+  myZoom(theOther.myZoom),
29
+  myAspect(theOther.myAspect),
30
+  myZScreen(theOther.myZScreen),
31
+  myIOD(theOther.myIOD),
32
+  myFrustL(theOther.myFrustL),
33
+  myFrustR(theOther.myFrustR),
34
+  myFrustM(theOther.myFrustM),
35
+  myFrust(NULL),
36
+  myIsPersp(theOther.myIsPersp) {
37
+    myFrust = &myFrustM;
38
+    if(theOther.myFrust == &theOther.myFrustL) {
39
+        myFrust = &myFrustL;
40
+    } else if(theOther.myFrust == &theOther.myFrustR) {
41
+        myFrust = &myFrustR;
42
+    }
43
+    updateFrustum();
44
+}
45
+
46
+void StGLProjCamera::copyFrom(const StGLProjCamera& theOther) {
47
+    myMatrix = theOther.myMatrix;
48
+    myMatrixMono = theOther.myMatrixMono;
49
+    myVrFrustumL = theOther.myVrFrustumL;
50
+    myVrFrustumR = theOther.myVrFrustumR;
51
+    myIsCustomFrust = theOther.myIsCustomFrust;
52
+    myFOVy = theOther.myFOVy;
53
+    myZoom = theOther.myZoom;
54
+    myAspect = theOther.myAspect;
55
+    myZScreen = theOther.myZScreen;
56
+    myIOD = theOther.myIOD;
57
+    myFrustL = theOther.myFrustL;
58
+    myFrustR = theOther.myFrustR;
59
+    myFrustM = theOther.myFrustM;
60
+    myIsPersp = theOther.myIsPersp;
61
+
62
+    myFrust = &myFrustM;
63
+    if(theOther.myFrust == &theOther.myFrustL) {
64
+        myFrust = &myFrustL;
65
+    } else if(theOther.myFrust == &theOther.myFrustR) {
66
+        myFrust = &myFrustR;
67
+    }
68
+    updateFrustum();
69
+}
70
+
71
 void StGLProjCamera::getZParams(const GLdouble theZValue,
72
                                 StRectD_t&     theSectRect) const {
73
     if(myIsPersp) {
74
@@ -94,14 +146,35 @@
75
     return std::atan2(aDYHalf, myFrustM.zNear * myZoom);
76
 }
77
 
78
+void StGLProjCamera::resetCustomProjection() {
79
+    myVrFrustumL = StRectF_t();
80
+    myVrFrustumR = StRectF_t();
81
+    myIsCustomFrust = false;
82
+    updateFrustum();
83
+}
84
+
85
+void StGLProjCamera::setCustomProjection(const StRectF_t& theLeft, const StRectF_t& theRight) {
86
+    myVrFrustumL = theLeft;
87
+    myVrFrustumR = theRight;
88
+    myIsCustomFrust = true;
89
+    updateFrustum();
90
+}
91
+
92
 void StGLProjCamera::updateFrustum() {
93
     // sets top of frustum based on FOVy and near clipping plane
94
+    const GLfloat aZNear = myFrustM.zNear;
95
+    GLfloat aDXStereoShift = (0.5f * myIOD) * aZNear / myZScreen;
96
+
97
     GLfloat aDYHalf = myIsPersp
98
-                    ? (myZoom * myFrustM.zNear * std::tan(ST_DTR_HALF * myFOVy))
99
-                    : (myZoom * myFrustM.zNear); ///
100
-    // sets right of frustum based on aspect ratio
101
+                    ? (myZoom * aZNear * std::tan(ST_DTR_HALF * myFOVy))
102
+                    : (myZoom * aZNear);
103
     GLfloat aDXHalf = myAspect * aDYHalf;
104
-    GLfloat aDXStereoShift = (0.5f * myIOD) * myFrustM.zNear / myZScreen;
105
+    /*GLfloat aDXHalf = aDYHalf;
106
+    if(myAspect > 1.0f) {
107
+        aDXHalf *= myAspect;
108
+    } else {
109
+        aDYHalf /= myAspect;
110
+    }*/
111
 
112
     // frustum for left view
113
     myFrustL.yTop    =  aDYHalf;
114
@@ -122,6 +195,19 @@
115
     myFrustM.xRight  =  aDXHalf;
116
     myFrustM.xTranslation = 0.0f;
117
 
118
+    if(myIsCustomFrust) {
119
+        myFrustL.yTop    = aZNear * myVrFrustumL.top();
120
+        myFrustL.yBottom = aZNear * myVrFrustumL.bottom();
121
+        myFrustL.xLeft   = aZNear * myVrFrustumL.left();
122
+        myFrustL.xRight  = aZNear * myVrFrustumL.right();
123
+
124
+        myFrustR.yTop    = aZNear * myVrFrustumR.top();
125
+        myFrustR.yBottom = aZNear * myVrFrustumR.bottom();
126
+        myFrustR.xLeft   = aZNear * myVrFrustumR.left();
127
+        myFrustR.xRight  = aZNear * myVrFrustumR.right();
128
+        myFrustL.xTranslation = myFrustR.xTranslation = 0.0f;
129
+    }
130
+
131
     // update current matrix
132
     setupMatrix();
133
 }
134
sview-17_04.tar.gz/StShared/StGLQuadTexture.cpp -> sview-20_08.tar.gz/StShared/StGLQuadTexture.cpp Changed
123
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2012 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -19,7 +19,9 @@
9
 : StGLTexture(GL_RGB8),
10
 #endif
11
   myDataSize(1.0f, 1.0f),
12
-  myDisplayRatio(1.0f) {
13
+  myDisplayRatio(1.0f),
14
+  myPAR(1.0f),
15
+  myPanorama(StPanorama_OFF) {
16
     //
17
 }
18
 
19
@@ -50,34 +52,43 @@
20
                                      const GLsizei     theTextureSizeY) {
21
     // test existing size / new size
22
     /// TODO (Kirill Gavrilov#8) we can automatically reduce texture size here
23
-    if((theTexture.getSizeX() < theTextureSizeX) ||
24
-       (theTexture.getSizeY() < theTextureSizeY) ||
25
-       !theTexture.isValid()) {
26
-        ST_DEBUG_LOG("Requested texture size (" + theTextureSizeX + 'x' + theTextureSizeY
27
-                   + ") larger than current texture size(" + theTexture.getSizeX() + 'x' + theTexture.getSizeY() + ')');
28
-        const GLsizei anOriginalSizeX = theTexture.getSizeX();
29
-        const GLsizei anOriginalSizeY = theTexture.getSizeY();
30
-
31
-        const GLint aMaxTexDim = theCtx.getMaxTextureSize();
32
-        GLsizei aNewSizeX = stMin(theTextureSizeX, GLsizei(aMaxTexDim));
33
-        GLsizei aNewSizeY = stMin(theTextureSizeY, GLsizei(aMaxTexDim));
34
-        if(!theCtx.arbNPTW) {
35
-            aNewSizeX = getPowerOfTwo(theTextureSizeX, GLsizei(aMaxTexDim));
36
-            aNewSizeY = getPowerOfTwo(theTextureSizeY, GLsizei(aMaxTexDim));
37
+    if(theTexture.isValid()) {
38
+        if(theTexture.getSizeX() == theTextureSizeX
39
+        && theTexture.getSizeY() == theTextureSizeY) {
40
+            return;
41
         }
42
-        if((aNewSizeY != anOriginalSizeY)
43
-        || (aNewSizeX != anOriginalSizeX)) {
44
-            if(!theTexture.initTrash(theCtx, aNewSizeX, aNewSizeY)) {
45
-                theTexture.initTrash(theCtx,
46
-                                     (anOriginalSizeX > 0) ? anOriginalSizeX : 512,
47
-                                     (anOriginalSizeY > 0) ? anOriginalSizeY : 512);
48
-                ST_DEBUG_LOG("FAILED to Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ")!");
49
-            } else {
50
-                ST_DEBUG_LOG("Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ") success!");
51
-            }
52
+
53
+        if(theTexture.getTarget() != GL_TEXTURE_CUBE_MAP
54
+        && theTexture.getSizeX() >= theTextureSizeX
55
+        && theTexture.getSizeY() >= theTextureSizeY) {
56
+            return;
57
+        }
58
+    }
59
+
60
+    ST_DEBUG_LOG("Requested texture size (" + theTextureSizeX + 'x' + theTextureSizeY
61
+                + ") larger than current texture size(" + theTexture.getSizeX() + 'x' + theTexture.getSizeY() + ')');
62
+    const GLsizei anOriginalSizeX = theTexture.getSizeX();
63
+    const GLsizei anOriginalSizeY = theTexture.getSizeY();
64
+
65
+    const GLint aMaxTexDim = theCtx.getMaxTextureSize();
66
+    GLsizei aNewSizeX = stMin(theTextureSizeX, GLsizei(aMaxTexDim));
67
+    GLsizei aNewSizeY = stMin(theTextureSizeY, GLsizei(aMaxTexDim));
68
+    if(!theCtx.arbNPTW) {
69
+        aNewSizeX = getPowerOfTwo(theTextureSizeX, GLsizei(aMaxTexDim));
70
+        aNewSizeY = getPowerOfTwo(theTextureSizeY, GLsizei(aMaxTexDim));
71
+    }
72
+    if((aNewSizeY != anOriginalSizeY)
73
+    || (aNewSizeX != anOriginalSizeX)) {
74
+        if(!theTexture.initTrash(theCtx, aNewSizeX, aNewSizeY)) {
75
+            theTexture.initTrash(theCtx,
76
+                                  (anOriginalSizeX > 0) ? anOriginalSizeX : 512,
77
+                                  (anOriginalSizeY > 0) ? anOriginalSizeY : 512);
78
+            ST_DEBUG_LOG("FAILED to Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ")!");
79
         } else {
80
-            ST_DEBUG_LOG("Not possible to Increase the texture size!");
81
+            ST_DEBUG_LOG("Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ") success!");
82
         }
83
+    } else {
84
+        ST_DEBUG_LOG("Not possible to Increase the texture size!");
85
     }
86
 }
87
 
88
@@ -100,20 +111,24 @@
89
 }
90
 
91
 void StGLFrameTextures::setMinMagFilter(StGLContext& theCtx,
92
-                                        const GLenum theMinMagFilter) {
93
-    myTextures[0].setMinMagFilter(theCtx, theMinMagFilter);
94
+                                        const GLenum theMinFilter,
95
+                                        const GLenum theMagFilter) {
96
+    myTextures[0].setMinMagFilter(theCtx, theMinFilter, theMagFilter);
97
     /// TODO (Kirill Gavrilov#4) investigate
98
-    myTextures[1].setMinMagFilter(theCtx, GL_LINEAR);
99
-    myTextures[2].setMinMagFilter(theCtx, GL_LINEAR);
100
-    myTextures[3].setMinMagFilter(theCtx, GL_LINEAR);
101
+    const GLenum aMinFilter = theMinFilter != GL_NEAREST ? theMinFilter : GL_LINEAR;
102
+    const GLenum aMagFilter = theMagFilter != GL_NEAREST ? theMagFilter : GL_LINEAR;
103
+    myTextures[1].setMinMagFilter(theCtx, aMinFilter, aMagFilter);
104
+    myTextures[2].setMinMagFilter(theCtx, aMinFilter, aMagFilter);
105
+    myTextures[3].setMinMagFilter(theCtx, aMinFilter, aMagFilter);
106
 }
107
 
108
 void StGLQuadTexture::setMinMagFilter(StGLContext& theCtx,
109
-                                      const GLenum theMinMagFilter) {
110
-    myTextures[FRONT_TEXTURE +  LEFT_TEXTURE].setMinMagFilter(theCtx, theMinMagFilter);
111
-    myTextures[FRONT_TEXTURE + RIGHT_TEXTURE].setMinMagFilter(theCtx, theMinMagFilter);
112
-    myTextures[BACK_TEXTURE  +  LEFT_TEXTURE].setMinMagFilter(theCtx, theMinMagFilter);
113
-    myTextures[BACK_TEXTURE  + RIGHT_TEXTURE].setMinMagFilter(theCtx, theMinMagFilter);
114
+                                        const GLenum theMinFilter,
115
+                                        const GLenum theMagFilter) {
116
+    myTextures[FRONT_TEXTURE +  LEFT_TEXTURE].setMinMagFilter(theCtx, theMinFilter, theMagFilter);
117
+    myTextures[FRONT_TEXTURE + RIGHT_TEXTURE].setMinMagFilter(theCtx, theMinFilter, theMagFilter);
118
+    myTextures[BACK_TEXTURE  +  LEFT_TEXTURE].setMinMagFilter(theCtx, theMinFilter, theMagFilter);
119
+    myTextures[BACK_TEXTURE  + RIGHT_TEXTURE].setMinMagFilter(theCtx, theMinFilter, theMagFilter);
120
 }
121
 
122
 StGLQuadTexture::StGLQuadTexture()
123
sview-17_04.tar.gz/StShared/StGLTextFormatter.cpp -> sview-20_08.tar.gz/StShared/StGLTextFormatter.cpp Changed
127
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2012-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2012-2018 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -10,6 +10,8 @@
9
 
10
 #include <StGL/StGLVertexBuffer.h>
11
 
12
+#include <algorithm>
13
+
14
 /**
15
  * Auxiliary function to translate rectangles by the vector.
16
  */
17
@@ -395,6 +397,27 @@
18
     }
19
 }
20
 
21
+void StGLTextFormatter::flipLeftRight(size_t theCharFrom, size_t theCharTo) {
22
+    if(theCharFrom == theCharTo
23
+    || theCharTo == size_t(-1)) {
24
+        return;
25
+    }
26
+
27
+    float aRight = myRects[theCharTo].px.right();
28
+    for(size_t aCharIter = theCharFrom; aCharIter < theCharTo; ++aCharIter) {
29
+        StGLRect&       aRect1 = myRects[aCharIter + 0].px;
30
+        const StGLRect& aRect2 = myRects[aCharIter + 1].px;
31
+        float aStepX = aRect2.left() - aRect1.left();
32
+        aRect1.moveRightTo(aRight);
33
+        aRight -= aStepX;
34
+    }
35
+
36
+    StGLRect& aRectLast = myRects[theCharTo].px;
37
+    aRectLast.moveRightTo(aRight);
38
+
39
+    std::reverse (myRects.begin() + theCharFrom, (theCharTo + 1) == myRects.size() ? myRects.end() : myRects.begin() + theCharTo + 1);
40
+}
41
+
42
 void StGLTextFormatter::format(const GLfloat theWidth,
43
                                const GLfloat theHeight) {
44
     if(myRectsNb == 0 || myIsFormatted) {
45
@@ -412,6 +435,8 @@
46
     // split text into lines and apply horizontal alignment
47
     myPenCurrLine = -myAscender;
48
     size_t aRectIter = 0;
49
+    size_t aFlipLower = 0, aFlipInnerLower = 0;
50
+    bool isRight2Left = false, isLeft2RightInner = false;
51
     for(StUtf8Iter anIter = myString.iterator(); *anIter != 0; ++anIter) {
52
         const stUtf32_t aCharThis = *anIter;
53
         if(aCharThis == '\x0D') {
54
@@ -423,6 +448,14 @@
55
                 myAlignWidth = myRects[aLastRect].px.right();
56
                 ///toCorrectXAlignment = true;
57
             }
58
+            if(isRight2Left) {
59
+                if(isLeft2RightInner) {
60
+                    flipLeftRight(aFlipInnerLower, aLastRect);
61
+                    isLeft2RightInner = false;
62
+                }
63
+                flipLeftRight(aFlipLower, aLastRect);
64
+                aFlipLower = aLastRect + 1;
65
+            }
66
             newLine(aLastRect);
67
             continue;
68
         } else if(aCharThis == ' ') {
69
@@ -430,6 +463,28 @@
70
             continue;
71
         }
72
 
73
+        if(StFTFont::isRightToLeft(aCharThis)) {
74
+            if(!isRight2Left) {
75
+                isRight2Left = true;
76
+                aFlipLower = aRectIter;
77
+            } else if(isLeft2RightInner) {
78
+                flipLeftRight(aFlipInnerLower, aRectIter - 1);
79
+                isLeft2RightInner = false;
80
+            }
81
+        } else if(isRight2Left) {
82
+            if((aCharThis >= '0' && aCharThis <= '9')
83
+            || (isLeft2RightInner && (aCharThis == '.' || aCharThis == ','))) {
84
+                if(!isLeft2RightInner) {
85
+                    isLeft2RightInner = true;
86
+                    aFlipInnerLower = aRectIter;
87
+                }
88
+            } else {
89
+                isRight2Left = false;
90
+                flipLeftRight(aFlipLower, aRectIter - 1);
91
+                aFlipLower = aRectIter;
92
+            }
93
+        }
94
+
95
         GLfloat aWidth = myRects[aRectIter].px.right() - myLineLeft;
96
         myTextWidth = stMax(myTextWidth, aWidth);
97
         if(theWidth > 0.0f && aWidth >= theWidth) {
98
@@ -439,6 +494,14 @@
99
                 aLastRect = aRectIter - 1;
100
             }
101
 
102
+            if(isRight2Left) {
103
+                if(isLeft2RightInner) {
104
+                    flipLeftRight(aFlipInnerLower, aLastRect);
105
+                    isLeft2RightInner = false;
106
+                }
107
+                flipLeftRight(aFlipLower, aLastRect);
108
+                aFlipLower = aLastRect + 1;
109
+            }
110
             newLine(aLastRect);
111
         }
112
 
113
@@ -449,6 +512,13 @@
114
     if(myRectsNb != 0) {
115
         myTextWidth = stMax(myTextWidth, myRects[myRectsNb - 1].px.right() - myLineLeft);
116
     }
117
+    if(isRight2Left) {
118
+        if(isLeft2RightInner) {
119
+            flipLeftRight(aFlipInnerLower, myRectsNb - 1);
120
+            isLeft2RightInner = false;
121
+        }
122
+        flipLeftRight(aFlipLower, myRectsNb - 1);
123
+    }
124
     newLine(myRectsNb - 1);
125
     if(myRectsNb != 0
126
     && myAlignWidth <= 0.0f) {
127
sview-17_04.tar.gz/StShared/StGLTexture.cpp -> sview-20_08.tar.gz/StShared/StGLTexture.cpp Changed
502
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -11,48 +11,76 @@
9
 #include <StImage/StImagePlane.h>
10
 
11
 #include <StGLCore/StGLCore20.h>
12
+#include <StGL/StGLArbFbo.h>
13
 #include <StGL/StGLContext.h>
14
 
15
 #include <StStrings/StLogger.h>
16
 #include <stAssert.h>
17
 
18
-bool StGLTexture::getInternalFormat(const StGLContext&  theCtx,
19
-                                    const StImagePlane& theData,
20
-                                    GLint&              theInternalFormat) {
21
-    (void )theCtx;
22
-    // sized formats are not supported by OpenGL ES
23
-    switch(theData.getFormat()) {
24
+#ifndef GL_R16
25
+    #define GL_R16      0x822A
26
+    #define GL_R16F     0x822D
27
+    #define GL_R32F     0x822E
28
+    #define GL_RGB16F   0x881B
29
+    #define GL_RGBA32F  0x8814
30
+    #define GL_RGB32F   0x8815
31
+    #define GL_RGBA16F  0x881A
32
+    #define GL_RGB16F   0x881B
33
+    #define GL_RGB4     0x804F
34
+    #define GL_RGB5     0x8050
35
+    #define GL_RGB8     0x8051
36
+    #define GL_RGB10    0x8052
37
+    #define GL_RGB12    0x8053
38
+    #define GL_RGB16    0x8054
39
+    #define GL_RGBA8    0x8058
40
+    #define GL_RGB10_A2 0x8059
41
+    #define GL_RGBA12   0x805A
42
+    #define GL_RGBA16   0x805B
43
+    //#define GL_ALPHA4   0x803B
44
+    #define GL_ALPHA8   0x803C
45
+    #define GL_ALPHA16  0x803E
46
+
47
+    #define GL_HALF_FLOAT                     0x140B
48
+    #define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
49
+#endif
50
+
51
+bool StGLTexture::getInternalFormat(const StGLContext& theCtx,
52
+                                    const StImagePlane::ImgFormat theFormat,
53
+                                    GLint& theInternalFormat) {
54
+    switch(theFormat) {
55
         case StImagePlane::ImgRGBAF:
56
-        case StImagePlane::ImgBGRAF:
57
-        #if defined(GL_ES_VERSION_2_0)
58
-            theInternalFormat = GL_RGBA;
59
-        #else
60
+        case StImagePlane::ImgBGRAF: // BGRA requires texture swizzling on OpenGL ES
61
             theInternalFormat = GL_RGBA32F;
62
-        #endif
63
+            if(!theCtx.arbTexFloat) {
64
+            #if defined(GL_ES_VERSION_2_0)
65
+                return false;
66
+            #else
67
+                theInternalFormat = GL_RGBA8;
68
+            #endif
69
+            }
70
             return true;
71
         case StImagePlane::ImgRGBF:
72
-        case StImagePlane::ImgBGRF:
73
-        #if defined(GL_ES_VERSION_2_0)
74
-            theInternalFormat = GL_RGB;
75
-        #else
76
+        case StImagePlane::ImgBGRF: // BGR requires texture swizzling on OpenGL ES
77
             theInternalFormat = GL_RGB32F;
78
-        #endif
79
+            if(!theCtx.arbTexFloat) {
80
+            #if defined(GL_ES_VERSION_2_0)
81
+                return false;
82
+            #else
83
+                theInternalFormat = GL_RGB8;
84
+            #endif
85
+            }
86
             return true;
87
         case StImagePlane::ImgRGBA:
88
         case StImagePlane::ImgBGRA:
89
         #if defined(GL_ES_VERSION_2_0)
90
-            theInternalFormat = GL_RGBA;
91
+            theInternalFormat = GL_RGBA; // non-sized for compatibility with OpenGL ES 2.0
92
         #else
93
             theInternalFormat = GL_RGBA8;
94
         #endif
95
             return true;
96
         case StImagePlane::ImgRGBA64:
97
-        #if defined(GL_ES_VERSION_2_0)
98
-            theInternalFormat = GL_RGBA;
99
-        #else
100
-            theInternalFormat = GL_RGBA16;
101
-        #endif
102
-            return true;
103
+            theInternalFormat = theCtx.arbTexRG ? GL_RGBA16 : GL_RGBA8;
104
+            return theCtx.extTexR16;
105
         case StImagePlane::ImgRGB: {
106
             theInternalFormat = GL_RGB8;
107
             return true;
108
@@ -68,61 +96,52 @@
109
         case StImagePlane::ImgBGR: {
110
             theInternalFormat = GL_RGB8;
111
         #if defined(GL_ES_VERSION_2_0)
112
-            return false;
113
+            return false; // still can be done via swizzling...
114
         #else
115
             return true;
116
         #endif
117
         }
118
         case StImagePlane::ImgBGR32:
119
-        #if defined(GL_ES_VERSION_2_0)
120
             theInternalFormat = GL_RGB8;
121
-            if(!theCtx.extTexBGRA8) {
122
-                return false;
123
+        #if defined(GL_ES_VERSION_2_0)
124
+            if(theCtx.extTexBGRA8) {
125
+                // GL_EXT_texture_format_BGRA8888 has been introduced for OpenGL ES 1.0
126
+                // and does not defined sized format supported by OpenGL ES 3.0+
127
+                theInternalFormat = GL_BGRA_EXT;
128
+            } else {
129
+                return false; // still can be done via swizzling...
130
             }
131
-
132
-            // GL_EXT_texture_format_BGRA8888 has been introduced for OpenGL ES 1.0
133
-            // and does not defined sized format supported by OpenGL ES 3.0+
134
-            theInternalFormat = GL_BGRA_EXT;
135
-        #else
136
-            theInternalFormat = GL_RGB8;
137
         #endif
138
             return true;
139
         case StImagePlane::ImgRGB48:
140
-        #if defined(GL_ES_VERSION_2_0)
141
-            theInternalFormat = GL_RGB;
142
-        #else
143
             theInternalFormat = GL_RGB16;
144
-        #endif
145
-            return true;
146
+            return theCtx.extTexR16;
147
         case StImagePlane::ImgGrayF:
148
-        #if defined(GL_ES_VERSION_2_0)
149
-            theInternalFormat = GL_ALPHA;
150
-        #else
151
-            //theInternalFormat = GL_R32F;    // OpenGL3+ hardware
152
-            //theInternalFormat = GL_ALPHA32F_ARB;
153
-            theInternalFormat = GL_ALPHA16; // backward compatibility
154
-        #endif
155
+            theInternalFormat = GL_R32F;
156
+            if(!theCtx.arbTexFloat || !theCtx.arbTexRG) {
157
+            #if defined(GL_ES_VERSION_2_0)
158
+                return false;
159
+            #else
160
+                // there is also GL_ALPHA32F_ARB
161
+                theInternalFormat = theCtx.arbTexRG ? GL_R16 : GL_ALPHA16;
162
+            #endif
163
+            }
164
             return true;
165
         case StImagePlane::ImgGray16:
166
-        #if defined(GL_ES_VERSION_2_0)
167
-            theInternalFormat = GL_ALPHA;
168
-        #else
169
-            //theInternalFormat = GL_R16;   // OpenGL3+ hardware
170
-            theInternalFormat = GL_ALPHA16; // backward compatibility
171
+            theInternalFormat = GL_R16; // equals to GL_R16_EXT on OpenGL ES extension
172
+        #if !defined(GL_ES_VERSION_2_0)
173
+            theInternalFormat = theCtx.arbTexRG ? GL_R16 : GL_ALPHA16;
174
         #endif
175
-            return true;
176
+            return theCtx.extTexR16;
177
         case StImagePlane::ImgGray:
178
         #if defined(GL_ES_VERSION_2_0)
179
-            theInternalFormat = GL_ALPHA;
180
+            theInternalFormat = theCtx.arbTexRG ? GL_R8 : GL_ALPHA;
181
         #else
182
-            // this texture format is deprecated with OpenGL3+, use GL_R8 (GL_RED) instead
183
-            //theInternalFormat = GL_R8;   // OpenGL3+ hardware
184
-            theInternalFormat = GL_ALPHA8; // backward compatibility
185
+            theInternalFormat = theCtx.arbTexRG ? GL_R8 : GL_ALPHA8;
186
         #endif
187
             return true;
188
         case StImagePlane::ImgUV:
189
-            // this texture format is deprecated with OpenGL3+, use GL_R8 (GL_RED) instead
190
-            //theInternalFormat = GL_RG8;   // OpenGL3+ hardware
191
+            //theInternalFormat = theCtx.arbTexRG ? GL_RG8 : GL_LUMINANCE_ALPHA; // OpenGL3+
192
             theInternalFormat = GL_LUMINANCE_ALPHA;
193
             return true;
194
         default:
195
@@ -134,28 +153,21 @@
196
                                 const StImagePlane& theData,
197
                                 GLenum& thePixelFormat,
198
                                 GLenum& theDataType) {
199
-#if !defined(GL_ES_VERSION_2_0)
200
-    (void )theCtx;
201
-#endif
202
     thePixelFormat = GL_RGB;
203
     theDataType    = GL_UNSIGNED_BYTE;
204
     switch(theData.getFormat()) {
205
         case StImagePlane::ImgGray: {
206
-            // we fill ALPHA channel in the texture!
207
-            //thePixelFormat = GL_RED;
208
-            thePixelFormat = GL_ALPHA;
209
+            thePixelFormat = theCtx.arbTexRG ? GL_RED : GL_ALPHA;
210
             theDataType = GL_UNSIGNED_BYTE;
211
             return true;
212
         }
213
         case StImagePlane::ImgGray16: {
214
-            // we fill ALPHA channel in the texture!
215
-            //thePixelFormat = GL_RED;
216
-            thePixelFormat = GL_ALPHA;
217
+            thePixelFormat = theCtx.arbTexRG ? GL_RED : GL_ALPHA;
218
             theDataType = GL_UNSIGNED_SHORT;
219
             return true;
220
         }
221
         case StImagePlane::ImgUV: {
222
-            //thePixelFormat = GL_RG;
223
+            //thePixelFormat = theCtx.arbTexRG ? GL_RG : GL_LUMINANCE_ALPHA;
224
             thePixelFormat = GL_LUMINANCE_ALPHA;
225
             theDataType = GL_UNSIGNED_BYTE;
226
             return true;
227
@@ -204,8 +216,7 @@
228
             return true;
229
         }
230
         case StImagePlane::ImgGrayF: {
231
-            //thePixelFormat = GL_RED;
232
-            thePixelFormat = GL_ALPHA;
233
+            thePixelFormat = theCtx.arbTexRG ? GL_RED : GL_ALPHA;
234
             theDataType = GL_FLOAT;
235
             return true;
236
         }
237
@@ -241,30 +252,6 @@
238
     }
239
 }
240
 
241
-#ifndef GL_R16
242
-    #define GL_R16      0x822A
243
-    #define GL_R16F     0x822D
244
-    #define GL_R32F     0x822E
245
-    #define GL_RGB16F   0x881B
246
-    #define GL_RGBA32F  0x8814
247
-    #define GL_RGB32F   0x8815
248
-    #define GL_RGBA16F  0x881A
249
-    #define GL_RGB16F   0x881B
250
-    #define GL_RGB4     0x804F
251
-    #define GL_RGB5     0x8050
252
-    #define GL_RGB8     0x8051
253
-    #define GL_RGB10    0x8052
254
-    #define GL_RGB12    0x8053
255
-    #define GL_RGB16    0x8054
256
-    #define GL_RGBA8    0x8058
257
-    #define GL_RGB10_A2 0x8059
258
-    #define GL_RGBA12   0x805A
259
-    #define GL_RGBA16   0x805B
260
-    //#define GL_ALPHA4   0x803B
261
-    #define GL_ALPHA8   0x803C
262
-    #define GL_ALPHA16  0x803E
263
-#endif
264
-
265
 bool StGLTexture::isAlphaFormat(const GLint theInternalFormat) {
266
     switch(theInternalFormat) {
267
         // RED variations (GL_RED, OpenGL 3.0+)
268
@@ -371,6 +358,49 @@
269
     }
270
 }
271
 
272
+/**
273
+ * Return appropriate data type for specified internal format.
274
+ */
275
+static GLenum getDataType(GLint theInternalFormat) {
276
+    switch(theInternalFormat) {
277
+        case GL_RED:
278
+        case GL_R8:
279
+        case GL_RGB:
280
+        case GL_RGB8:
281
+        case GL_RGBA:
282
+        case GL_RGBA8:
283
+        case GL_BGRA_EXT:
284
+        case GL_ALPHA:
285
+        case GL_ALPHA8:
286
+        case GL_LUMINANCE:
287
+        case GL_LUMINANCE_ALPHA:
288
+            return GL_UNSIGNED_BYTE;
289
+        case GL_R16:
290
+        case GL_RGB16:
291
+        case GL_RGBA16:
292
+        case GL_ALPHA16:
293
+            return GL_UNSIGNED_SHORT;
294
+        case GL_R16F:
295
+        case GL_RGB16F:
296
+        case GL_RGBA16F:
297
+            return GL_HALF_FLOAT;
298
+        case GL_R32F:
299
+        case GL_RGB32F:
300
+        case GL_RGBA32F:
301
+            return GL_FLOAT;
302
+        /*case GL_RGB4:
303
+        case GL_RGB5:
304
+        case GL_RGB10:
305
+        case GL_RGB12:
306
+        case GL_RGBA12:
307
+            return GL_UNSIGNED_BYTE;*/
308
+        case GL_RGB10_A2:
309
+            return GL_UNSIGNED_INT_2_10_10_10_REV;
310
+        default:
311
+            return GL_UNSIGNED_BYTE;
312
+    }
313
+}
314
+
315
 StGLTexture::StGLTexture()
316
 : mySizeX(0),
317
   mySizeY(0),
318
@@ -378,7 +408,9 @@
319
   myTextFormat(GL_RGBA8),
320
   myTextureId(NO_TEXTURE),
321
   myTextureUnit(GL_TEXTURE0),
322
-  myTextureFilt(GL_LINEAR) {
323
+  myFilterMin(GL_LINEAR),
324
+  myFilterMag(GL_LINEAR),
325
+  myHasMipMaps(0) {
326
     //
327
 }
328
 
329
@@ -389,7 +421,9 @@
330
   myTextFormat(theTextureFormat),
331
   myTextureId(NO_TEXTURE),
332
   myTextureUnit(GL_TEXTURE0),
333
-  myTextureFilt(GL_LINEAR) {
334
+  myFilterMin(GL_LINEAR),
335
+  myFilterMag(GL_LINEAR),
336
+  myHasMipMaps(0) {
337
     //
338
 }
339
 
340
@@ -490,14 +524,15 @@
341
     theCtx.stglResetErrors();
342
 #endif
343
 
344
+    myHasMipMaps = 0;
345
     if(!isValid()) {
346
         theCtx.core20fwd->glGenTextures(1, &myTextureId); // Create The Texture
347
     }
348
     bind(theCtx);
349
 
350
     // texture interpolation parameters - could be overridden later
351
-    theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MAG_FILTER, myTextureFilt);
352
-    theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MIN_FILTER, myTextureFilt);
353
+    theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MIN_FILTER, myFilterMin);
354
+    theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MAG_FILTER, myFilterMag);
355
     theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
356
     theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);
357
 
358
@@ -506,9 +541,12 @@
359
         return false;
360
     }
361
 
362
+    // NULL is passed to glTexImage2D(), so that there is no actual data to be interpreted.
363
+    // However, OpenGL ES raises GL_INVALID_OPERATION if invalid type is passed.
364
+    const GLenum aDataType = getDataType(myTextFormat);
365
     GLint anInternalFormat = myTextFormat;
366
 #if defined(GL_ES_VERSION_2_0)
367
-    if(!theCtx.isGlGreaterEqual(3, 0)) {
368
+    if(!theCtx.isGlGreaterEqual(3, 0) && aDataType == GL_UNSIGNED_BYTE) {
369
         // sized formats are not supported here
370
         anInternalFormat = theDataFormat;
371
     }
372
@@ -524,12 +562,12 @@
373
         for(int aTargetIter = 0; aTargetIter < 6; ++aTargetIter) {
374
             theCtx.core20fwd->glTexImage2D(aTargets[aTargetIter], 0, anInternalFormat,
375
                                        mySizeX, mySizeY, 0,
376
-                                       theDataFormat, GL_UNSIGNED_BYTE, theData);
377
+                                       theDataFormat, aDataType, theData);
378
         }
379
     } else {
380
         theCtx.core20fwd->glTexImage2D(myTarget, 0, anInternalFormat,
381
                                        mySizeX, mySizeY, 0,
382
-                                       theDataFormat, GL_UNSIGNED_BYTE, theData);
383
+                                       theDataFormat, aDataType, theData);
384
     }
385
 #if defined(GL_ES_VERSION_2_0)
386
     // proxy texture is unavailable - check for errors
387
@@ -568,17 +606,40 @@
388
 }
389
 
390
 void StGLTexture::setMinMagFilter(StGLContext& theCtx,
391
-                                  const GLenum theMinMagFilter) {
392
-    if(!isValid()) {
393
-        myTextureFilt = theMinMagFilter;
394
+                                  const GLenum theMinFilter,
395
+                                  const GLenum theMagFilter) {
396
+    const bool needsMipMaps = theMinFilter != GL_NEAREST
397
+                           && theMinFilter != GL_LINEAR;
398
+    if(myFilterMin == theMinFilter
399
+    && myFilterMag == theMagFilter
400
+    && (!needsMipMaps || myHasMipMaps != 0)) {
401
         return;
402
-    } else if(myTextureFilt == theMinMagFilter) {
403
+    }
404
+
405
+    myFilterMin = theMinFilter;
406
+    myFilterMag = theMagFilter;
407
+    if(!isValid()) {
408
         return;
409
     }
410
-    myTextureFilt = theMinMagFilter;
411
+
412
     bind(theCtx);
413
-        theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MAG_FILTER, myTextureFilt);
414
-        theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MIN_FILTER, myTextureFilt);
415
+        if(needsMipMaps && myHasMipMaps == 0) {
416
+            theCtx.arbFbo->glGenerateMipmap(myTarget);
417
+            const GLenum anErr = glGetError();
418
+            if(anErr != GL_NO_ERROR) {
419
+                // note that OpenGL ES 2.0 does not support mip-map generation of non-power-of-two textures
420
+                ST_ERROR_LOG("Failed to generate mipmap levels with error " + theCtx.stglErrorToString(anErr));
421
+                myHasMipMaps = -1;
422
+            } else {
423
+                myHasMipMaps = 1;
424
+            }
425
+        }
426
+        GLenum aMinFilter = !needsMipMaps || myHasMipMaps == 1
427
+                          ? myFilterMin
428
+                          : GL_LINEAR;
429
+        theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MIN_FILTER, aMinFilter);
430
+        theCtx.core20fwd->glTexParameteri(myTarget, GL_TEXTURE_MAG_FILTER, myFilterMag);
431
+
432
     unbind(theCtx);
433
 }
434
 
435
@@ -595,6 +656,19 @@
436
 
437
 bool StGLTexture::fillPatch(StGLContext&        theCtx,
438
                             const StImagePlane& theData,
439
+                            const GLenum        theTarget,
440
+                            const GLsizei       theRowFrom,
441
+                            const GLsizei       theRowTo) {
442
+#ifdef __ANDROID__
443
+    GLsizei aBatchRows = 0;
444
+#else
445
+    GLsizei aBatchRows = 128; // TODO does it makes sense nowadays?
446
+#endif
447
+    return fillPatch(theCtx, theData, theTarget, theRowFrom, theRowTo, aBatchRows);
448
+}
449
+
450
+bool StGLTexture::fillPatch(StGLContext&        theCtx,
451
+                            const StImagePlane& theData,
452
                             GLenum              theTarget,
453
                             const GLsizei       theRowFrom,
454
                             const GLsizei       theRowTo,
455
@@ -605,6 +679,7 @@
456
     if(theData.isNull() || !isValid()) {
457
         return false;
458
     }
459
+
460
     GLenum aPixelFormat, aDataType;
461
     if(!getDataFormat(theCtx, theData, aPixelFormat, aDataType)) {
462
         return false;
463
@@ -620,6 +695,7 @@
464
         return false;
465
     }
466
 
467
+    myHasMipMaps = 0;
468
     bind(theCtx);
469
 
470
     // setup the alignment
471
@@ -639,13 +715,13 @@
472
         toBatchCopy  = false;
473
     }
474
 
475
-    if(!theCtx.hasUnpack
476
+    if(!theCtx.getDeviceCaps().hasUnpack
477
     && anExtraBytes >= anAligment) {
478
         toBatchCopy = false;
479
     }
480
 
481
     if(toBatchCopy) {
482
-        if(theCtx.hasUnpack) {
483
+        if(theCtx.getDeviceCaps().hasUnpack) {
484
             theCtx.core20fwd->glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(aPixelsWidth));
485
         }
486
 
487
@@ -667,12 +743,12 @@
488
                                               theData.getData(aRow, 0));
489
         }
490
 
491
-        if(theCtx.hasUnpack) {
492
+        if(theCtx.getDeviceCaps().hasUnpack) {
493
             theCtx.core20fwd->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
494
         }
495
     } else {
496
         // copy row by row copy (the image plane greater than texture or batch copy is impossible)
497
-        if(theCtx.hasUnpack) {
498
+        if(theCtx.getDeviceCaps().hasUnpack) {
499
             theCtx.core20fwd->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
500
         }
501
 
502
sview-17_04.tar.gz/StShared/StGLTextureData.cpp -> sview-20_08.tar.gz/StShared/StGLTextureData.cpp Changed
347
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -10,8 +10,11 @@
9
 #include <StStrings/StLogger.h>
10
 
11
 #include <StGLCore/StGLCore11.h>
12
+#include <StGL/StGLContext.h>
13
 
14
-StGLTextureData::StGLTextureData()
15
+#include <StAV/StAVImage.h>
16
+
17
+StGLTextureData::StGLTextureData(const StHandle<StGLTextureUploadParams>& theUploadParams)
18
 : myPrev(NULL),
19
   myNext(NULL),
20
   myDataPtr(NULL),
21
@@ -20,6 +23,7 @@
22
   myPts(0.0),
23
   mySrcFormat(StFormat_AUTO),
24
   myCubemapFormat(StCubemap_OFF),
25
+  myUploadParams(theUploadParams),
26
   myFillFromRow(0),
27
   myFillRows(0) {
28
     //
29
@@ -316,10 +320,18 @@
30
             theCoeffX = 6;
31
             theCoeffY = 1;
32
             return true;
33
+        } else if(thePlane.getSizeY() / 6 == thePlane.getSizeX()) {
34
+            theCoeffX = 1;
35
+            theCoeffY = 6;
36
+            return true;
37
         } else if(thePlane.getSizeX() / 3 == thePlane.getSizeY() / 2) {
38
             theCoeffX = 3;
39
             theCoeffY = 2;
40
             return true;
41
+        } else if(thePlane.getSizeX() / 2 == thePlane.getSizeY() / 3) {
42
+            theCoeffX = 2;
43
+            theCoeffY = 3;
44
+            return true;
45
         }
46
         return false;
47
     }
48
@@ -589,12 +601,17 @@
49
 }
50
 
51
 void StGLTextureData::validateCubemap(const StCubemap theCubemap) {
52
-    if(theCubemap != StCubemap_Packed) {
53
+    if(theCubemap != StCubemap_Packed
54
+    && theCubemap != StCubemap_PackedEAC) {
55
         myCubemapFormat = StCubemap_OFF;
56
         return;
57
     }
58
 
59
     myCubemapFormat = theCubemap;
60
+    if(theCubemap == StCubemap_PackedEAC) {
61
+        return;
62
+    }
63
+
64
     size_t aCoeffs[2] = {0, 0};
65
     if(!myDataL.isNull()) {
66
         for(size_t aPlaneId = 0; aPlaneId < 4; ++aPlaneId) {
67
@@ -623,50 +640,168 @@
68
         return;
69
     }
70
 
71
-    if(myCubemapFormat != StCubemap_Packed) {
72
+    if(myCubemapFormat != StCubemap_Packed
73
+    && myCubemapFormat != StCubemap_PackedEAC) {
74
         theFrameTexture.fillPatch(theCtx, theData, GL_TEXTURE_2D, myFillFromRow, myFillFromRow + myFillRows);
75
         return;
76
     }
77
 
78
     size_t aCoeffs[2] = {0, 0};
79
-    if(!checkCubeMap(theData, aCoeffs[0], aCoeffs[1])) {
80
-        return;
81
+    if(myCubemapFormat == StCubemap_PackedEAC) {
82
+        if(theData.getSizeX() > theData.getSizeY()) {
83
+            aCoeffs[0] = 3;
84
+            aCoeffs[1] = 2;
85
+        } else {
86
+            aCoeffs[0] = 2;
87
+            aCoeffs[1] = 3;
88
+        }
89
+    } else {
90
+        if(!checkCubeMap(theData, aCoeffs[0], aCoeffs[1])) {
91
+            return;
92
+        }
93
     }
94
 
95
-    const size_t aPatch = theData.getSizeX() / aCoeffs[0];
96
-    if(aPatch < 2) {
97
+    const size_t aPatchX = theData.getSizeX() / aCoeffs[0];
98
+    const size_t aPatchY = theData.getSizeY() / aCoeffs[1];
99
+    if(aPatchX < 2 || aPatchY < 2) {
100
         return;
101
     }
102
 
103
-    const GLenum aTargets[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X,
104
-                                 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
105
-                                 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
106
-                                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
107
-                                 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
108
-                                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
109
+    static const GLenum THE_SIDES_GL[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
110
+                                            GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
111
+                                            GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
112
+    static const GLenum THE_SIDES_EAC32[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
113
+                                               GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Y };
114
+    static const GLenum THE_SIDES_EAC23[6] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
115
+                                               GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
116
+                                               GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y };
117
+
118
+    const GLenum* aTargets = myCubemapFormat == StCubemap_PackedEAC
119
+                           ? (aCoeffs[1] == 3 ? THE_SIDES_EAC23 : THE_SIDES_EAC32)
120
+                           : THE_SIDES_GL;
121
     for(size_t aTargetIter = 0; aTargetIter < 6; ++aTargetIter) {
122
         StImagePlane aPlane;
123
-        const bool isSecondRow = (aCoeffs[1] == 2 && aTargetIter >= 3);
124
-        const size_t aLeft = isSecondRow ? (aPatch * (aTargetIter - 3)) : (aPatch * aTargetIter);
125
-        const size_t aTop  = isSecondRow ? aPatch : 0;
126
+        size_t aTop = 0, aLeft = 0;
127
+        bool toTranspose = false;
128
+        switch(aCoeffs[1]) {
129
+            case 1: { // 6x1
130
+                aLeft = aPatchX * aTargetIter;
131
+                aTop  = 0;
132
+                break;
133
+            }
134
+            case 2: { // 3x2
135
+                if(aTargetIter >= 3) {
136
+                    // second row
137
+                    aLeft = aPatchX * (aTargetIter - 3);
138
+                    aTop  = aPatchY;
139
+                    if(myCubemapFormat == StCubemap_PackedEAC) {
140
+                        toTranspose = true;
141
+                    }
142
+                } else {
143
+                    // first row
144
+                    aLeft = aPatchX * aTargetIter;
145
+                    aTop  = 0;
146
+                }
147
+                break;
148
+            }
149
+            case 3: { // 2x3
150
+                if(aTargetIter >= 4) {
151
+                    // third row
152
+                    aLeft = aPatchX * (aTargetIter - 4);
153
+                    aTop  = aPatchY * 2;
154
+                } else if(aTargetIter >= 2) {
155
+                    // second row
156
+                    aLeft = aPatchX * (aTargetIter - 2);
157
+                    aTop  = aPatchY;
158
+                } else {
159
+                    // first row
160
+                    aLeft = aPatchX * aTargetIter;
161
+                    aTop  = 0;
162
+                }
163
+
164
+                if(myCubemapFormat == StCubemap_PackedEAC
165
+                && (aTargetIter % 2) == 0) {
166
+                    toTranspose = true;
167
+                }
168
+                break;
169
+            }
170
+            case 6: { // 1x6
171
+                aLeft = 0;
172
+                aTop  = aPatchY * aTargetIter;
173
+                break;
174
+            }
175
+        }
176
         if(!aPlane.initWrapper(theData.getFormat(), const_cast<GLubyte* >(theData.getData(aTop, aLeft)),
177
-                               aPatch, aPatch, theData.getSizeRowBytes())) {
178
+                               aPatchX, aPatchY, theData.getSizeRowBytes())) {
179
             ST_DEBUG_LOG("StGLTextureData::fillTexture(). wrapping failure");
180
             continue;
181
         }
182
-        theFrameTexture.fillPatch(theCtx, aPlane, aTargets[aTargetIter], myFillFromRow, myFillFromRow + myFillRows);
183
+
184
+        StImagePlane* aResPlane = &aPlane;
185
+
186
+        // this is too slow without multi-threading
187
+        (void )toTranspose;
188
+        /*if(toTranspose) {
189
+            StImagePlane& aTmpPlane = theCtx.getTmpImagePlane1();
190
+            aTmpPlane.initTransposedCopy(aPlane, aCoeffs[1] != 3);
191
+            aResPlane = &aTmpPlane;
192
+        }
193
+
194
+        if(aPatchX != aPatchY) {
195
+            size_t aPatch = stMax(aPatchX, aPatchY);
196
+            StImagePlane& aTmpPlane2 = theCtx.getTmpImagePlane2();
197
+            if(aTmpPlane2.getFormat() != aResPlane->getFormat()
198
+            || aTmpPlane2.getSizeX() != aResPlane->getSizeX()
199
+            || aTmpPlane2.getSizeY() != aResPlane->getSizeY()) {
200
+                aTmpPlane2.initTrash(aResPlane->getFormat(), aPatch, aPatch);
201
+            }
202
+            if(!aTmpPlane2.isNull()) {
203
+                StAVImage::resizePlane(*aResPlane, aTmpPlane2);
204
+                aResPlane = &aTmpPlane2;
205
+            }
206
+        }*/
207
+
208
+        theFrameTexture.fillPatch(theCtx, *aResPlane, aTargets[aTargetIter], myFillFromRow, myFillFromRow + myFillRows);
209
     }
210
 }
211
 
212
-static void setupDataRectangle(const StImagePlane& theImagePlane,
213
-                               const GLfloat       thePixelRatio,
214
-                               StGLFrameTexture&   theTextureFrame) {
215
+void StGLTextureData::setupDataRectangle(const StImagePlane& theImagePlane,
216
+                                         const GLfloat       thePixelRatio,
217
+                                         StGLFrameTexture&   theTextureFrame) {
218
     if(theImagePlane.isNull() || !theTextureFrame.isValid()) {
219
         return;
220
     }
221
 
222
-    const GLfloat aSizeXFloat = stMin(GLfloat(theImagePlane.getSizeX()), GLfloat(theTextureFrame.getSizeX()));
223
-    const GLfloat aSizeYFloat = stMin(GLfloat(theImagePlane.getSizeY()), GLfloat(theTextureFrame.getSizeY()));
224
+    size_t anImgSizeX = theImagePlane.getSizeX();
225
+    size_t anImgSizeY = theImagePlane.getSizeY();
226
+
227
+    StPanorama aPano = StPanorama_OFF;
228
+    size_t aCoeffs[2] = {0, 0};
229
+    if(myCubemapFormat == StCubemap_Packed
230
+    && checkCubeMap(theImagePlane, aCoeffs[0], aCoeffs[1])) {
231
+        anImgSizeX = anImgSizeX / aCoeffs[0];
232
+        anImgSizeY = anImgSizeY / aCoeffs[1];
233
+        switch(aCoeffs[0]) {
234
+            case 1: aPano = StPanorama_Cubemap1_6; break;
235
+            case 3: aPano = StPanorama_Cubemap3_2; break;
236
+            case 6: aPano = StPanorama_Cubemap6_1; break;
237
+        }
238
+    } else if(myCubemapFormat == StCubemap_PackedEAC) {
239
+        if(theImagePlane.getSizeX() > theImagePlane.getSizeY()) {
240
+            aCoeffs[0] = 3;
241
+            aCoeffs[1] = 2;
242
+            aPano = StPanorama_Cubemap3_2ytb;
243
+        } else {
244
+            aCoeffs[0] = 2;
245
+            aCoeffs[1] = 3;
246
+            aPano = StPanorama_Cubemap2_3ytb;
247
+        }
248
+        anImgSizeX = anImgSizeX / aCoeffs[0];
249
+        anImgSizeY = anImgSizeY / aCoeffs[1];
250
+    }
251
+
252
+    const GLfloat aSizeXFloat = stMin(GLfloat(anImgSizeX), GLfloat(theTextureFrame.getSizeX()));
253
+    const GLfloat aSizeYFloat = stMin(GLfloat(anImgSizeY), GLfloat(theTextureFrame.getSizeY()));
254
     StGLVec2 aDataSize (aSizeXFloat / GLfloat(theTextureFrame.getSizeX()),
255
                         aSizeYFloat / GLfloat(theTextureFrame.getSizeY()));
256
     if(aDataSize.x() > 1.0f) {
257
@@ -677,6 +812,8 @@
258
     }
259
     theTextureFrame.setDataSize(aDataSize);
260
     theTextureFrame.setDisplayRatio((thePixelRatio * aSizeXFloat) / aSizeYFloat);
261
+    theTextureFrame.setPixelRatio(thePixelRatio);
262
+    theTextureFrame.setPackedPanorama(aPano);
263
 }
264
 
265
 void StGLTextureData::setupAttributes(StGLFrameTextures& stFrameTextures, const StImage& theImage) {
266
@@ -701,7 +838,7 @@
267
             continue;
268
         }
269
 
270
-        if(!StGLTexture::getInternalFormat(theCtx, anImgPlane, anInternalFormat)) {
271
+        if(!StGLTexture::getInternalFormat(theCtx, anImgPlane.getFormat(), anInternalFormat)) {
272
             aTexture.release(theCtx);
273
             continue;
274
         }
275
@@ -717,6 +854,23 @@
276
             aTarget = GL_TEXTURE_CUBE_MAP;
277
             aSizeX  = aSizeX / GLsizei(aCoeffs[0]);
278
             aSizeY  = aSizeY / GLsizei(aCoeffs[1]);
279
+            if(aSizeX < 1) {
280
+                aTexture.release(theCtx);
281
+                continue;
282
+            }
283
+            aSizeX  = stMax(aSizeX, aSizeY); // cubemap requires squared images
284
+            aSizeY  = stMax(aSizeX, aSizeY);
285
+        } else if(theCubemap == StCubemap_PackedEAC) {
286
+            if(aSizeX > aSizeY) {
287
+                aSizeX /= 3;
288
+                aSizeY /= 2;
289
+            } else {
290
+                aSizeX /= 2;
291
+                aSizeY /= 3;
292
+            }
293
+            aTarget = GL_TEXTURE_CUBE_MAP;
294
+            aSizeX  = stMax(aSizeX, aSizeY); // cubemap requires squared images
295
+            aSizeY  = stMax(aSizeX, aSizeY);
296
         }
297
         if(aSizeX < 1) {
298
             aTexture.release(theCtx);
299
@@ -743,16 +897,38 @@
300
         theQTexture.getBack(StGLQuadTexture::LEFT_TEXTURE).setSource(StHandle<StStereoParams>());
301
         theQTexture.getBack(StGLQuadTexture::RIGHT_TEXTURE).setSource(StHandle<StStereoParams>());
302
 
303
-        // TODO (Kirill Gavrilov#9) this value is meanfull only for PageFlip,
304
-        //                          also rows number may be replaced with bytes count
305
-        static const GLsizei UPDATED_ROWS_MAX = 1088; // we use optimal value to update 1080p video frame at-once
306
-        GLsizei maxRows    = stMin(GLsizei(myDataL.getSizeY()), theQTexture.getBack(StGLQuadTexture::LEFT_TEXTURE).getSizeY());
307
-        GLsizei iterations = (maxRows / (UPDATED_ROWS_MAX * 2)) + 1;
308
-        if(!myDataR.isNull()) {
309
-            maxRows    = stMax(maxRows, stMin(GLsizei(myDataR.getSizeY()), theQTexture.getBack(StGLQuadTexture::RIGHT_TEXTURE).getSizeY()));
310
-            iterations = maxRows / UPDATED_ROWS_MAX + 1;
311
+        const int aNbRowsL = stMin(int(myDataL.getSizeY()), theQTexture.getBack(StGLQuadTexture::LEFT_TEXTURE).getSizeY());
312
+        const int aNbRowsR = !myDataR.isNull()
313
+                           ? stMin(int(myDataR.getSizeY()), theQTexture.getBack(StGLQuadTexture::RIGHT_TEXTURE).getSizeY())
314
+                           : 0;
315
+        const int aNbMaxRows = stMax(aNbRowsL, aNbRowsR);
316
+
317
+        const int aMaxUploadChunkMiB   = myUploadParams->MaxUploadChunkMiB;
318
+        const int aMaxUploadIterations = myUploadParams->MaxUploadIterations;
319
+        int aNbIters = 1;
320
+        if(aMaxUploadChunkMiB > 0 && aMaxUploadIterations > 1) {
321
+            size_t aStride = 0;
322
+            for(int aPlaneIter = 0; aPlaneIter < 4; ++aPlaneIter) {
323
+                const StImagePlane& aPlaneL = myDataL.getPlane(aPlaneIter);
324
+                if(!aPlaneL.isNull()) {
325
+                    // don't use aPlane.getSizeRowBytes() here since it may contain extra padding for side-by-side input
326
+                    aStride += aPlaneL.getSizeX() * aPlaneL.getSizePixelBytes();
327
+                }
328
+                if(!myDataR.isNull()) {
329
+                    const StImagePlane& aPlaneR = myDataR.getPlane(aPlaneIter);
330
+                    if(!aPlaneR.isNull()) {
331
+                        aStride += aPlaneR.getSizeX() * aPlaneR.getSizePixelBytes();
332
+                    }
333
+                }
334
+            }
335
+
336
+            const int aNbMaxFrameRows = int((size_t(aMaxUploadChunkMiB) * 1024 * 1024) / aStride);
337
+            aNbIters = stMin(aMaxUploadIterations, aNbMaxRows / aNbMaxFrameRows);
338
+        }
339
+        myFillRows = (aNbIters > 0) ? (aNbMaxRows / aNbIters) : aNbMaxRows;
340
+        if(myCubemapFormat == StCubemap_Packed || myCubemapFormat == StCubemap_PackedEAC) {
341
+            myFillRows = INT_MAX; /// TODO handle cube maps incremental updates specificall
342
         }
343
-        myFillRows = maxRows / iterations;
344
         myFillFromRow = 0;
345
     }
346
 
347
sview-17_04.tar.gz/StShared/StGLTextureQueue.cpp -> sview-20_08.tar.gz/StShared/StGLTextureQueue.cpp Changed
51
 
1
@@ -23,14 +23,22 @@
2
   myIsInUpdTexture(false),
3
   myIsReadyToSwap(false),
4
   myToCompress(false),
5
-  myHasStream(false) {
6
+  myHasStream(false),
7
+  myUploadParams(new StGLTextureUploadParams()) {
8
     ST_ASSERT(myQueueSizeMax >= 2, "StGLTextureQueue() - queue size limit should be >= 2");
9
+    // 1920x1080@YUV420p   ~  3 MiB
10
+    // 1920x1080@RGB8      ~  6 MiB
11
+    // 3840x2160@YUV420p   ~ 12 MiB
12
+    // 3840x2160@RGB8      ~ 24 MiB
13
+    // 3840x2160@YUV420p16 ~ 24 MiB
14
+    myUploadParams->MaxUploadChunkMiB   = 6;
15
+    myUploadParams->MaxUploadIterations = 1;
16
 
17
     // we create 'empty' queue
18
-    myDataFront = new StGLTextureData();
19
+    myDataFront = new StGLTextureData(myUploadParams);
20
     StGLTextureData* iter = myDataFront;
21
     for(size_t i = 1; i < myQueueSizeMax; ++i) {
22
-        iter->setNext(new StGLTextureData());
23
+        iter->setNext(new StGLTextureData(myUploadParams));
24
         iter = iter->getNext();
25
     }
26
     iter->setNext(myDataFront); // data in loop
27
@@ -186,12 +194,13 @@
28
     myMutexPop.unlock();
29
 }
30
 
31
-void StGLTextureQueue::drop(const size_t theCount) {
32
+void StGLTextureQueue::drop(const size_t theCount,
33
+                            double& thePtsFront) {
34
     myMutexPop.lock();
35
     myMutexPush.lock();
36
     myMutexSize.lock();
37
         if(myQueueSize < 2) {
38
-            // to small queue
39
+            // too small queue
40
             myMutexSize.unlock();
41
             myMutexPush.unlock();
42
             myMutexPop.unlock();
43
@@ -203,6 +212,7 @@
44
         for(size_t i = 0; i < decr; ++i, myDataFront = myDataFront->getNext()) {
45
             myDataFront->resetStParams();
46
         }
47
+        thePtsFront = myDataFront->getPTS();
48
         // reset queue
49
         myQueueSize -= decr;
50
         // empty texture update sequence
51
sview-20_08.tar.gz/StShared/StGLUVCylinder.cpp Added
77
 
1
@@ -0,0 +1,75 @@
2
+/**
3
+ * Copyright © 2019-2020 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#include <StGLMesh/StGLUVCylinder.h>
11
+
12
+#include <StGLCore/StGLCore20.h>
13
+#include <StGL/StGLContext.h>
14
+
15
+StGLUVCylinder::StGLUVCylinder(const StGLVec3& theCenter,
16
+                               const float theHeight,
17
+                               const float theRadius,
18
+                               const int theRings)
19
+: StGLMesh(GL_TRIANGLE_STRIP),
20
+  myCenter(theCenter),
21
+  myRadius(theRadius),
22
+  myHeight(theHeight),
23
+  myAngleFrom(0.0f),
24
+  myAngleTo(float(M_PI * 2.0)),
25
+  myNbRings(theRings) {
26
+    //
27
+}
28
+
29
+StGLUVCylinder::StGLUVCylinder(const StGLVec3& theCenter,
30
+                               const float theHeight,
31
+                               const float theRadius,
32
+                               const float theAngleFrom,
33
+                               const float theAngleTo,
34
+                               const int theRings)
35
+: StGLMesh(GL_TRIANGLE_STRIP),
36
+  myCenter(theCenter),
37
+  myRadius(theRadius),
38
+  myHeight(theHeight),
39
+  myAngleFrom(theAngleFrom),
40
+  myAngleTo(theAngleTo),
41
+  myNbRings(theRings) {
42
+    //
43
+}
44
+
45
+
46
+StGLUVCylinder::~StGLUVCylinder() {
47
+    //
48
+}
49
+
50
+bool StGLUVCylinder::computeMesh() {
51
+    clearRAM();
52
+    if(myNbRings == 0) {
53
+        return false;
54
+    }
55
+
56
+    const int aNbVerts = (myNbRings + 1) * 2;
57
+    myVertices.initArray(aNbVerts);
58
+    myNormals .initArray(aNbVerts);
59
+    myTCoords .initArray(aNbVerts);
60
+
61
+    const float anAngle = myAngleTo - myAngleFrom;
62
+    for(int aRingIter = 0; aRingIter <= myNbRings; ++aRingIter) {
63
+        const float aPhi    = myAngleFrom + float(aRingIter) * anAngle / float(myNbRings);
64
+        const float aTexCrd = float(aRingIter) / float(myNbRings);
65
+        myTCoords.changeValue(aRingIter * 2 + 0) = StGLVec2(aTexCrd, 0.0f);
66
+        myTCoords.changeValue(aRingIter * 2 + 1) = StGLVec2(aTexCrd, 1.0f);
67
+
68
+        const StGLVec3 aNorm(cosf(aPhi), 0.0f, sinf(aPhi));
69
+        myNormals.changeValue(aRingIter * 2 + 0) = aNorm;
70
+        myNormals.changeValue(aRingIter * 2 + 1) = aNorm;
71
+
72
+        myVertices.changeValue(aRingIter * 2 + 0) = myCenter + aNorm * myRadius - StGLVec3(0.0f, myHeight * 0.5f, 0.0f);
73
+        myVertices.changeValue(aRingIter * 2 + 1) = myCenter + aNorm * myRadius + StGLVec3(0.0f, myHeight * 0.5f, 0.0f);
74
+    }
75
+    return true;
76
+}
77
sview-17_04.tar.gz/StShared/StGLUVSphere.cpp -> sview-20_08.tar.gz/StShared/StGLUVSphere.cpp Changed
59
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2012 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -12,22 +12,23 @@
9
 #include <StGLCore/StGLCore20.h>
10
 #include <StGL/StGLContext.h>
11
 
12
-/// TODO (Kirill Gavrilov#9) move to the common header
13
 namespace {
14
     static const GLfloat ST_PI     = 3.1415926535897932384626433832795f;
15
     static const GLfloat ST_TWOPI  = 6.2831853071795864769252867665590f;
16
     static const GLfloat ST_PIDIV2 = 1.5707963267948966192313216916397f;
17
-};
18
+}
19
 
20
 StGLUVSphere::StGLUVSphere(const StGLVec3& theCenter,
21
                            const GLfloat   theRadius,
22
-                           const size_t    theRings)
23
+                           const size_t    theRings,
24
+                           const bool      theIsHemisphere)
25
 : StGLMesh(GL_TRIANGLE_STRIP),
26
   myPrimCounts(1),
27
   myIndPointers(1),
28
   myCenter(theCenter),
29
   myRadius(theRadius),
30
-  myRings(theRings) {
31
+  myRings(theRings),
32
+  myIsHemisphere(theIsHemisphere) {
33
     //
34
 }
35
 
36
@@ -38,7 +39,8 @@
37
   myIndPointers(1),
38
   myCenter(theBndSphere.getCenter()),
39
   myRadius(theBndSphere.getRadius()),
40
-  myRings(theRings) {
41
+  myRings(theRings),
42
+  myIsHemisphere(false) {
43
     //
44
 }
45
 
46
@@ -73,7 +75,11 @@
47
         tcrd.y() = GLfloat(ringId) / GLfloat(aRingsCount);
48
 
49
         for(size_t pointId = 0; pointId <= pointPerRing; ++pointId) {
50
-            phi = GLfloat(pointId) * ST_TWOPI / GLfloat(pointPerRing);
51
+            if(myIsHemisphere) {
52
+                phi = ST_PIDIV2 + GLfloat(pointId) * ST_PI / GLfloat(pointPerRing);
53
+            } else {
54
+                phi = GLfloat(pointId) * ST_TWOPI / GLfloat(pointPerRing);
55
+            }
56
 
57
             tcrd.x() = GLfloat(pointId) / GLfloat(pointPerRing);
58
 
59
sview-17_04.tar.gz/StShared/StImage.cpp -> sview-20_08.tar.gz/StShared/StImage.cpp Changed
172
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -14,26 +14,151 @@
9
         case ImgColor_RGB:     return "ImgColor_RGB";
10
         case ImgColor_RGBA:    return "ImgColor_RGBA";
11
         case ImgColor_GRAY:    return "ImgColor_GRAY";
12
+        case ImgColor_XYZ:     return "ImgColor_XYZ";
13
         case ImgColor_YUV:     return "ImgColor_YUV";
14
+        case ImgColor_YUVA:    return "ImgColor_YUVA";
15
         case ImgColor_CMYK:    return "ImgColor_CMYK";
16
         case ImgColor_HSV:     return "ImgColor_HSV";
17
         case ImgColor_HSL:     return "ImgColor_HSL";
18
-        default:               return "ImgColor_UNKNOWN";
19
     }
20
+    return "ImgColor_UNKNOWN";
21
 #else
22
     switch(theColorModel) {
23
         case ImgColor_RGB:     return "RGB";
24
         case ImgColor_RGBA:    return "RGBA";
25
         case ImgColor_GRAY:    return "Grayscale";
26
+        case ImgColor_XYZ:     return "XYZ";
27
         case ImgColor_YUV:     return "YUV";
28
+        case ImgColor_YUVA:    return "YUVA";
29
         case ImgColor_CMYK:    return "CMYK";
30
         case ImgColor_HSV:     return "HSV";
31
         case ImgColor_HSL:     return "HSL";
32
-        default:               return StString("UNKNOWN[") + theColorModel + "]";
33
     }
34
+    return StString("UNKNOWN[") + theColorModel + "]";
35
 #endif
36
 }
37
 
38
+const char* StImage::formatImgPixelFormat() const {
39
+    switch(myColorModel) {
40
+        case ImgColor_RGB:
41
+        case ImgColor_RGBA:
42
+        case ImgColor_GRAY: {
43
+            switch(myPlanes[0].getFormat()) {
44
+                case StImagePlane::ImgGray:    return "gray8";
45
+                case StImagePlane::ImgGray16:  return "gray16";
46
+                case StImagePlane::ImgRGB:     return "rgb24";
47
+                case StImagePlane::ImgBGR:     return "bgr24";
48
+                case StImagePlane::ImgRGB32:   return "rgb32";
49
+                case StImagePlane::ImgBGR32:   return "bgr32";
50
+                case StImagePlane::ImgRGB48:   return "rgb48";
51
+                case StImagePlane::ImgRGBA:    return "rgba32";
52
+                case StImagePlane::ImgBGRA:    return "bgra32";
53
+                case StImagePlane::ImgRGBA64:  return "rgba64";
54
+                case StImagePlane::ImgGrayF:   return "grayf";
55
+                case StImagePlane::ImgRGBF:    return "rgbf";
56
+                case StImagePlane::ImgBGRF:    return "bgrf";
57
+                case StImagePlane::ImgRGBAF:   return "rgbaf";
58
+                case StImagePlane::ImgBGRAF:   return "bgraf";
59
+                case StImagePlane::ImgUV:      return "uv";
60
+                case StImagePlane::ImgUNKNOWN: return "unknown";
61
+            }
62
+            return "invalid_rgb";
63
+        }
64
+        case ImgColor_XYZ: {
65
+            switch(myPlanes[0].getFormat()) {
66
+                case StImagePlane::ImgRGB:     return "xyz8";
67
+                case StImagePlane::ImgRGB48:   return "xyz12";
68
+                case StImagePlane::ImgRGBF:    return "xyzf";
69
+                default: break;
70
+            }
71
+            return "invalid_xyz";
72
+        }
73
+        case ImgColor_YUV:
74
+        case ImgColor_YUVA: {
75
+            const bool  hasAlpha = myColorModel == ImgColor_YUVA;
76
+            const size_t aDelimX = (myPlanes[1].getSizeX() > 0) ? (myPlanes[0].getSizeX() / myPlanes[1].getSizeX()) : 1;
77
+            const size_t aDelimY = (myPlanes[1].getSizeY() > 0) ? (myPlanes[0].getSizeY() / myPlanes[1].getSizeY()) : 1;
78
+            if(myPlanes[1].getFormat() == StImagePlane::ImgUV) {
79
+                return "nv12";
80
+            } else if(aDelimX == 1 && aDelimY == 1) {
81
+                switch(myColorScale) {
82
+                    case StImage::ImgScale_Mpeg:
83
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
84
+                             ? (hasAlpha ? "yuva444p16" : "yuv444p16")
85
+                             : (hasAlpha ? "yuva444p"   : "yuv444p");
86
+                    case StImage::ImgScale_Mpeg9:
87
+                    case StImage::ImgScale_Jpeg9:
88
+                        return (hasAlpha ? "yuva444p9" : "yuv444p9");
89
+                    case StImage::ImgScale_Mpeg10:
90
+                    case StImage::ImgScale_Jpeg10:
91
+                        return (hasAlpha ? "yuva444p10" : "yuv444p10");
92
+                    case StImage::ImgScale_Full:
93
+                    default:
94
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
95
+                             ? (hasAlpha ? "yuvaj444p16" : "yuvj444p16")
96
+                             : (hasAlpha ? "yuvaj444p"   : "yuvj444p");
97
+                }
98
+            } else if(aDelimX == 2 && aDelimY == 2) {
99
+                switch(myColorScale) {
100
+                    case StImage::ImgScale_Mpeg:
101
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
102
+                             ? (hasAlpha ? "yuva420p16" : "yuv420p16")
103
+                             : (hasAlpha ? "yuva420p"   : "yuv420p");
104
+                    case StImage::ImgScale_Mpeg9:
105
+                    case StImage::ImgScale_Jpeg9:
106
+                        return (hasAlpha ? "yuva420p9" : "yuv420p9");
107
+                    case StImage::ImgScale_Mpeg10:
108
+                    case StImage::ImgScale_Jpeg10:
109
+                        return (hasAlpha ? "yuva420p10" : "yuv420p10");
110
+                    case StImage::ImgScale_Full:
111
+                    default:
112
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
113
+                             ? (hasAlpha ? "yuvaj420p16" : "yuvj420p16")
114
+                             : (hasAlpha ? "yuvaj420p"   : "yuvj420p");
115
+                }
116
+            } else if(aDelimX == 2 && aDelimY == 1) {
117
+                switch(myColorScale) {
118
+                    case StImage::ImgScale_Mpeg:
119
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
120
+                             ? (hasAlpha ? "yuva422p16" : "yuv422p16")
121
+                             : (hasAlpha ? "yuva422p"   : "yuv422p");
122
+                    case StImage::ImgScale_Mpeg9:
123
+                    case StImage::ImgScale_Jpeg9:
124
+                        return (hasAlpha ? "yuva422p9" : "yuv422p9");
125
+                    case StImage::ImgScale_Mpeg10:
126
+                    case StImage::ImgScale_Jpeg10:
127
+                        return (hasAlpha ? "yuva422p10" : "yuv422p10");
128
+                    case StImage::ImgScale_Full:
129
+                    default:
130
+                        return myPlanes[0].getFormat() == StImagePlane::ImgGray16
131
+                             ? (hasAlpha ? "yuvaj422p16" : "yuvj422p16")
132
+                             : (hasAlpha ? "yuvaj422p"   : "yuvj422p");
133
+                }
134
+            } else if(aDelimX == 1 && aDelimY == 2) {
135
+                return myColorScale == StImage::ImgScale_Mpeg
136
+                     ? (hasAlpha ? "yuva440p"  : "yuv440p")
137
+                     : (hasAlpha ? "yuvaj440p" : "yuvj440p");
138
+            } else if(aDelimX == 4 && aDelimY == 1) {
139
+                return myColorScale == StImage::ImgScale_Mpeg
140
+                     ? (hasAlpha ? "yuva411p"  : "yuv411p")
141
+                     : (hasAlpha ? "yuvaj411p" : "yuvj411p");
142
+            } else if(aDelimX == 4 && aDelimY == 4) {
143
+                return myColorScale == StImage::ImgScale_Mpeg
144
+                     ? (hasAlpha ? "yuva410p"  : "yuv410p")
145
+                     : (hasAlpha ? "yuvaj410p" : "yuvj410p");
146
+            }
147
+            return (hasAlpha ? "yuva_unknown" : "yuv_unknown");
148
+        }
149
+        case ImgColor_CMYK:
150
+            return "CMYK";
151
+        case ImgColor_HSV:
152
+            return "HSV";
153
+        case ImgColor_HSL:
154
+            return "HSL";
155
+    }
156
+    return "unknown";
157
+}
158
+
159
 StImage::StImage()
160
 : myPAR(1.0f),
161
   myColorModel(ImgColor_RGB),
162
@@ -194,7 +319,8 @@
163
                              const StImage& theImageR,
164
                              const int theSeparationDx,
165
                              const int theSeparationDy) {
166
-    const bool isYUV = theImageL.getColorModel() == StImage::ImgColor_YUV;
167
+    const bool isYUV = theImageL.getColorModel() == StImage::ImgColor_YUV
168
+                    || theImageL.getColorModel() == StImage::ImgColor_YUVA;
169
     for(size_t aPlaneId = 0; aPlaneId < 4; ++aPlaneId) {
170
         float aScaleX = (theImageL.getPlane(aPlaneId).getSizeX() > 0) ? theImageL.getScaleFactorX(aPlaneId) : 1.0f;
171
         float aScaleY = (theImageL.getPlane(aPlaneId).getSizeY() > 0) ? theImageL.getScaleFactorY(aPlaneId) : 1.0f;
172
sview-17_04.tar.gz/StShared/StImageFile.cpp -> sview-20_08.tar.gz/StShared/StImageFile.cpp Changed
223
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -11,14 +11,61 @@
9
 #include <StImage/StDevILImage.h>
10
 #include <StImage/StFreeImage.h>
11
 #include <StImage/StWebPImage.h>
12
+#include <StImage/StStbImage.h>
13
 #include <StAV/StAVImage.h>
14
 #include <StFile/StFileNode.h>
15
 #include <StFile/StMIME.h>
16
+#include <StFile/StRawFile.h>
17
 
18
 #include <StStrings/StLogger.h>
19
 
20
+/**
21
+ * DDS Pixel Format structure.
22
+ */
23
+struct StDDSPixelFormat {
24
+    uint32_t Size;
25
+    uint32_t Flags;
26
+    uint32_t FourCC;
27
+    uint32_t RGBBitCount;
28
+    uint32_t RBitMask;
29
+    uint32_t GBitMask;
30
+    uint32_t BBitMask;
31
+    uint32_t ABitMask;
32
+};
33
+
34
+/**
35
+ * DDS File header structure.
36
+ */
37
+struct StDDSFileHeader {
38
+    /**
39
+     * Caps2 flag indicating complete (6 faces) cubemap.
40
+     */
41
+    enum { DDSCompleteCubemap = 0xFE00 };
42
+
43
+    /**
44
+     * Return TRUE if cubmap flag is set.
45
+     */
46
+    bool isCompleteCubemap() const { return (Caps2 & DDSCompleteCubemap) != 0; }
47
+
48
+    uint32_t Size;
49
+    uint32_t Flags;
50
+    uint32_t Height;
51
+    uint32_t Width;
52
+    uint32_t PitchOrLinearSize;
53
+    uint32_t Depth;
54
+    uint32_t MipMapCount;
55
+    uint32_t Reserved1[11];
56
+    StDDSPixelFormat PixelFormatDef;
57
+    uint32_t Caps;
58
+    uint32_t Caps2;
59
+    uint32_t Caps3;
60
+    uint32_t Caps4;
61
+    uint32_t Reserved2;
62
+};
63
+
64
 StImageFile::StImageFile()
65
-: mySrcFormat(StFormat_AUTO) {
66
+: mySrcFormat(StFormat_AUTO),
67
+  mySrcPanorama(StPanorama_OFF) {
68
     //
69
 }
70
 
71
@@ -41,6 +88,8 @@
72
     } else if(thePreferred.isEqualsIgnoreCase(stCString("WebP")) ||
73
               thePreferred.isEqualsIgnoreCase(stCString("StWebPImage"))) {
74
         aPreferred = ST_WEBP;
75
+    } else if(thePreferred.isEqualsIgnoreCase(stCString("stb"))) {
76
+        aPreferred = ST_STB;
77
     }
78
     return aPreferred;
79
 }
80
@@ -50,6 +99,7 @@
81
         case ST_FREEIMAGE: return "FreeImage";
82
         case ST_DEVIL:     return "DevIL";
83
         case ST_WEBP:      return "WebP";
84
+        case ST_STB:       return "stb";
85
         default:
86
         case ST_LIBAV:     return "FFmpeg";
87
     }
88
@@ -93,6 +143,9 @@
89
     } else if(anExt.isEqualsIgnoreCase(stCString("webpll"))
90
            || theMIMEType.getMIMEType().isEquals(stCString("image/webpll"))) {
91
         return StImageFile::ST_TYPE_WEBPLL;
92
+    } else if(anExt.isEqualsIgnoreCase(stCString("dds"))
93
+           || theMIMEType.getMIMEType().isEquals(stCString("image/vnd-ms.dds"))) {
94
+       return StImageFile::ST_TYPE_DDS;
95
     }
96
     return StImageFile::ST_TYPE_NONE;
97
 }
98
@@ -164,6 +217,12 @@
99
             }
100
             break;
101
         }
102
+        case ST_STB: {
103
+            if(StStbImage::init()) {
104
+                return new StStbImage();
105
+            }
106
+            break;
107
+        }
108
         default:
109
         case ST_LIBAV: {
110
             if(StAVImage::init()) {
111
@@ -180,6 +239,111 @@
112
     return StHandle<StImageFile>();
113
 }
114
 
115
+bool StImageFile::load(const StString& theFilePath,
116
+                       ImageType theImageType,
117
+                       uint8_t* theDataPtr, int theDataSize) {
118
+    if(theImageType == ST_TYPE_DDS) {
119
+        // Most image libraries ignore arrays/cubemaps in DDS file.
120
+        // As DDS format is pretty simple - parse it here and load cubemap as vertically stacked image.
121
+        StRawFile aRawFile(theFilePath);
122
+        if(theDataPtr == NULL) {
123
+            if(!aRawFile.readFile()) {
124
+                return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
125
+            }
126
+            theDataPtr = (uint8_t* )aRawFile.getBuffer();
127
+            theDataSize = (int )aRawFile.getSize();
128
+        }
129
+
130
+        if (theDataSize < 128
131
+         || memcmp (&theDataPtr[0], "DDS ", 4) != 0) {
132
+            return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
133
+        }
134
+
135
+        const StDDSFileHeader* aSrcHeader = (const StDDSFileHeader* )&theDataPtr[4];
136
+        if (aSrcHeader->Size != 124
137
+         || aSrcHeader->Width  == 0
138
+         || aSrcHeader->Height == 0
139
+         || aSrcHeader->Width != aSrcHeader->Height
140
+         || aSrcHeader->PixelFormatDef.Size != 32
141
+         || (aSrcHeader->Caps2 & StDDSFileHeader::DDSCompleteCubemap) != StDDSFileHeader::DDSCompleteCubemap) {
142
+            return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
143
+        }
144
+
145
+        const int aHeaderSize  = aSrcHeader->Size + 4;
146
+        const int aPayLoadSize = theDataSize - aHeaderSize;
147
+        if (aPayLoadSize % 6 != 0
148
+         || aPayLoadSize <= 0) {
149
+            return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
150
+        }
151
+
152
+        const int aTileDataSize = aPayLoadSize / 6;
153
+        StArray<uint8_t> aTileBuffer (aTileDataSize + aHeaderSize);
154
+        memcpy(&aTileBuffer.changeFirst(),  "DDS ", 4);
155
+        memcpy(&aTileBuffer.changeValue(4), aSrcHeader, aSrcHeader->Size);
156
+        StDDSFileHeader* aHeaderTile = (StDDSFileHeader* )&aTileBuffer.changeValue(4);
157
+        aHeaderTile->Caps2 &= ~(StDDSFileHeader::DDSCompleteCubemap);
158
+
159
+        StHandle<StImageFile> aTileImage = createEmpty();
160
+
161
+        memcpy(&aTileBuffer.changeValue(aHeaderSize), &theDataPtr[aHeaderSize], aTileDataSize);
162
+        if(!aTileImage->loadExtra(theFilePath, theImageType, &aTileBuffer.changeFirst(), (int )aTileBuffer.size(), false)
163
+         || aTileImage->isNull()
164
+         || aTileImage->getSizeX() < 1
165
+         || aTileImage->getSizeY() < 1
166
+         || aTileImage->getSizeX() != aTileImage->getSizeY()) {
167
+            return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
168
+        }
169
+
170
+        close();
171
+        nullify();
172
+        myMetadata   = aTileImage->myMetadata;
173
+        myStateDescr = aTileImage->myStateDescr;
174
+        mySrcFormat  = aTileImage->mySrcFormat;
175
+        setColorModel(aTileImage->getColorModel());
176
+        setColorScale(aTileImage->getColorScale());
177
+        setPixelRatio(aTileImage->getPixelRatio());
178
+        const bool isTopDownLayout = aTileImage->isTopDown();
179
+        for(size_t aPlaneId = 0; aPlaneId < 4; ++aPlaneId) {
180
+            const StImagePlane& aFromPlane = aTileImage->getPlane(aPlaneId);
181
+            const size_t aTileIndex = isTopDownLayout ? 0 : 5;
182
+            if(!aFromPlane.isNull()) {
183
+                if(!changePlane(aPlaneId).initTrash(aFromPlane.getFormat(), aFromPlane.getSizeX(), aFromPlane.getSizeX() * 6)) {
184
+                    return false;
185
+                }
186
+                changePlane(aPlaneId).setTopDown(aFromPlane.isTopDown());
187
+                memcpy(changePlane(aPlaneId).changeData() + aFromPlane.getSizeBytes() * aTileIndex,
188
+                       aFromPlane.getData(), aFromPlane.getSizeBytes());
189
+            }
190
+        }
191
+
192
+        for(size_t aTileIter = 1; aTileIter < 6; ++aTileIter) {
193
+            memcpy(&aTileBuffer.changeValue(aHeaderSize), &theDataPtr[aTileIter * aTileDataSize + aHeaderSize], aTileDataSize);
194
+            aTileImage = createEmpty();
195
+            if(!aTileImage->loadExtra(theFilePath, theImageType, &aTileBuffer.changeFirst(), (int )aTileBuffer.size(), false)
196
+             || aTileImage->isNull()
197
+             || aTileImage->getSizeX() != getSizeX()
198
+             || aTileImage->getSizeY() != getSizeX() // square
199
+             || aTileImage->getColorModel() != getColorModel()
200
+             || aTileImage->getPlane().getFormat() != getPlane().getFormat()) {
201
+                ST_ERROR_LOG("Internal error: DDS file is decoded into inconsistent tiles");
202
+                return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
203
+            }
204
+
205
+            const size_t aTileIndex = isTopDownLayout ? aTileIter : (5 - aTileIter);
206
+            for(size_t aPlaneId = 0; aPlaneId < 4; ++aPlaneId) {
207
+                const StImagePlane& aFromPlane = aTileImage->getPlane(aPlaneId);
208
+                if(!aFromPlane.isNull()) {
209
+                    memcpy(changePlane(aPlaneId).changeData() + aFromPlane.getSizeBytes() * aTileIndex,
210
+                           aFromPlane.getData(), aFromPlane.getSizeBytes());
211
+                }
212
+            }
213
+        }
214
+        mySrcPanorama = StPanorama_Cubemap1_6;
215
+        return true;
216
+    }
217
+    return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false);
218
+}
219
+
220
 StImageFileCounter::~StImageFileCounter() {}
221
 
222
 void StImageFileCounter::createReference(StHandle<StBufferCounter>& theOther) const {
223
sview-17_04.tar.gz/StShared/StImagePlane.cpp -> sview-20_08.tar.gz/StShared/StImagePlane.cpp Changed
50
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -26,9 +26,9 @@
9
         case ImgRGBAF:   return "ImgRGBAF";
10
         case ImgBGRAF:   return "ImgBGRAF";
11
         case ImgUV:      return "ImgUV";
12
-        case ImgUNKNOWN:
13
-        default:         return "ImgUNKNOWN";
14
+        case ImgUNKNOWN: return "ImgUNKNOWN";
15
     }
16
+    return "unknown";
17
 }
18
 
19
 StImagePlane::StImagePlane()
20
@@ -159,6 +159,29 @@
21
     return true;
22
 }
23
 
24
+bool StImagePlane::initTransposedCopy(const StImagePlane& theCopy,
25
+                                      const bool theIsClockwise) {
26
+    if(myImgFormat != theCopy.myImgFormat
27
+    || mySizeX != theCopy.mySizeX
28
+    || mySizeY != theCopy.mySizeY) {
29
+        if(!initTrash(theCopy.myImgFormat, theCopy.mySizeY, theCopy.mySizeX)) {
30
+            return false;
31
+        }
32
+    }
33
+
34
+    const size_t aPixelSize = getSizePixelBytes();
35
+    const size_t aSrcColFrom =  theIsClockwise ? theCopy.mySizeX - 1 : 0;
36
+    const size_t aSrcRowFrom = !theIsClockwise ? theCopy.mySizeY - 1 : 0;
37
+    const size_t aSrcColIncr = aSrcColFrom == 0 ? 1 : size_t(-1);
38
+    const size_t aSrcRowIncr = aSrcRowFrom == 0 ? 1 : size_t(-1);
39
+    for(size_t aDstRow = 0, aSrcCol = aSrcColFrom; aDstRow < mySizeY; ++aDstRow, aSrcCol += aSrcColIncr) {
40
+        for(size_t aDstCol = 0, aSrcRow = aSrcRowFrom; aDstCol < mySizeX; ++aDstCol, aSrcRow += aSrcRowIncr) {
41
+            stMemCpy(changeData(aDstRow, aDstCol), theCopy.getData(aSrcRow, aSrcCol), aPixelSize);
42
+        }
43
+    }
44
+    return true;
45
+}
46
+
47
 bool StImagePlane::initWrapper(const StImagePlane& theCopy) {
48
     if(!initWrapper(theCopy.myImgFormat, theCopy.myDataPtr,
49
                     theCopy.mySizeX, theCopy.mySizeY, theCopy.mySizeRowBytes)) {
50
sview-20_08.tar.gz/StShared/StJNIEnv.cpp Added
77
 
1
@@ -0,0 +1,75 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#include <StJNI/StJNIEnv.h>
11
+
12
+#include <StStrings/StLogger.h>
13
+#include <StThreads/StThread.h>
14
+
15
+#if defined(__ANDROID__)
16
+    #include <jni.h>
17
+#endif
18
+
19
+StJNIEnv::StJNIEnv(JavaVM* theJavaVM)
20
+: myJavaVM(theJavaVM),
21
+  myJniEnv(NULL),
22
+  myThreadId(0),
23
+  myToDetach(false) {
24
+    if(myJavaVM == NULL) {
25
+        return;
26
+    }
27
+
28
+#if defined(__ANDROID__)
29
+    void* aJniEnv = NULL;
30
+    switch(myJavaVM->GetEnv(&aJniEnv, JNI_VERSION_1_6)) {
31
+        case JNI_EDETACHED: {
32
+            if(myJavaVM->AttachCurrentThread(&myJniEnv, NULL) < 0) {
33
+                myJniEnv = NULL;
34
+                ST_ERROR_LOG("Failed to attach working thread to Java VM");
35
+                return;
36
+            }
37
+            myToDetach = true;
38
+            myThreadId = StThread::getCurrentThreadId();
39
+            break;
40
+        }
41
+        case JNI_OK: {
42
+            myJniEnv   = (JNIEnv* )aJniEnv;
43
+            myToDetach = false;
44
+            break;
45
+        }
46
+        case JNI_EVERSION: {
47
+            ST_ERROR_LOG("Failed to attach working thread to Java VM - JNI version is not supported");
48
+            break;
49
+        }
50
+        default: {
51
+            ST_ERROR_LOG("Failed to attach working thread to Java VM");
52
+            break;
53
+        }
54
+    }
55
+#endif
56
+}
57
+
58
+StJNIEnv::~StJNIEnv() {
59
+    detach();
60
+}
61
+
62
+void StJNIEnv::detach() {
63
+    if(myJavaVM != NULL
64
+    && myJniEnv != NULL
65
+    && myToDetach) {
66
+        if(myThreadId != StThread::getCurrentThreadId()) {
67
+            ST_ERROR_LOG("Internal error, StJNIEnv::detach() - attempt to detach from another thread");
68
+        }
69
+    #if defined(__ANDROID__)
70
+        myJavaVM->DetachCurrentThread();
71
+    #endif
72
+    }
73
+
74
+    myJniEnv   = NULL;
75
+    myToDetach = false;
76
+}
77
sview-17_04.tar.gz/StShared/StJpegParser.cpp -> sview-20_08.tar.gz/StShared/StJpegParser.cpp Changed
119
 
1
@@ -142,7 +142,8 @@
2
 StJpegParser::StJpegParser(const StCString& theFilePath)
3
 : StRawFile(theFilePath),
4
   myImages(NULL),
5
-  myStFormat(StFormat_AUTO) {
6
+  myStFormat(StFormat_AUTO),
7
+  myPanorama(StPanorama_OFF) {
8
     stMemZero(myOffsets, sizeof(myOffsets));
9
 #if !defined(_MSC_VER)
10
     (void )markerString;
11
@@ -157,7 +158,9 @@
12
     // destroy all images
13
     myImages.nullify();
14
     myComment.clear();
15
+    myXMP.clear();
16
     myStFormat = StFormat_AUTO;
17
+    myPanorama = StPanorama_OFF;
18
     myLength = 0;
19
     stMemZero(myOffsets, sizeof(myOffsets));
20
 }
21
@@ -232,6 +235,7 @@
22
     // parse the data
23
     StHandle<StJpegParser::Image> anImg = new StJpegParser::Image();
24
     anImg->Data = aData - 2;
25
+    bool toDetectCubemap = false;
26
 
27
     for(;;) {
28
         // search for the next marker in the file
29
@@ -251,6 +255,32 @@
30
         //ST_DEBUG_LOG(" #" + theImgCount + "." + theDepth + " [" + markerString(aMarker) + "] at position " + size_t(aData - myBuffer) + " / " + myLength); ///
31
         if(aMarker == M_EOI) {
32
             //ST_DEBUG_LOG("Jpeg, EOI at position " + size_t(aData - myBuffer) + " / " + myLength);
33
+
34
+            bool isPanoStereo = false;
35
+            if(toDetectCubemap && myPanorama == StPanorama_OFF) {
36
+                size_t aViewX = anImg->SizeX, aViewY = anImg->SizeY;
37
+                if(myStFormat == StFormat_SideBySide_LR || myStFormat == StFormat_SideBySide_RL) {
38
+                    aViewX /= 2;
39
+                } else if(myStFormat == StFormat_TopBottom_LR || myStFormat == StFormat_TopBottom_RL) {
40
+                    aViewY /= 2;
41
+                }
42
+                if(aViewX == aViewY * 6) {
43
+                    myPanorama = StPanorama_Cubemap6_1;
44
+                } else if(aViewX * 6 == aViewY) {
45
+                    myPanorama = StPanorama_Cubemap1_6;
46
+                } else if(aViewX * 2 == aViewY * 3) {
47
+                    myPanorama = StPanorama_Cubemap3_2;
48
+                }
49
+            } else if(anImg->get360PanoMakerNote(isPanoStereo)) {
50
+                if(myPanorama == StPanorama_OFF) {
51
+                    myPanorama = StPanorama_Sphere;
52
+                }
53
+                if(myStFormat == StFormat_AUTO
54
+                && isPanoStereo) {
55
+                    myStFormat = StFormat_TopBottom_LR;
56
+                }
57
+            }
58
+
59
             anImg->Length = size_t(aData - anImg->Data);
60
             return anImg;
61
         } else if(aMarker == M_SOI) {
62
@@ -369,6 +399,23 @@
63
                     }
64
                 } else if(stAreEqual(aData + 2, "http:", 5)) {
65
                     //ST_DEBUG_LOG("Image cotains XMP section");
66
+                    if(stAreEqual(aData + 2, "http://ns.adobe.com/xap/1.0/", 28)) { // XMP basic namespace
67
+                        myXMP = StString((char* )aData + 31, anItemLen - 31);
68
+                        {
69
+                          // GPano http://ns.google.com/photos/1.0/panorama/ namespace metadata.
70
+                          // Note possible cropped panorama parameters are ignored by sView.
71
+                          if(myXMP.isContains(stCString("<GPano:ProjectionType>equirectangular</GPano:ProjectionType>"))
72
+                          || myXMP.isContains(stCString("GPano:ProjectionType=\"equirectangular\""))) {
73
+                              // Google currently supports only equirectangular format
74
+                              myPanorama = StPanorama_Sphere;
75
+                          } else if(myXMP.isContains(stCString("<GPano:ProjectionType>cubemap</GPano:ProjectionType>"))
76
+                                 || myXMP.isContains(stCString("GPano:ProjectionType=\"cubemap\""))) {
77
+                              // this one doesn't yet exist, but try to support it
78
+                              toDetectCubemap = true;
79
+                          }
80
+                        }
81
+                        myXMP.clear();
82
+                    }
83
                 } else {
84
                     //ST_DEBUG_LOG("  @@@ APP2 " + StString((char* )aData + 2));
85
                 }
86
@@ -471,7 +518,10 @@
87
             return false;
88
         }
89
         stMemCpy(aNewData, myBuffer, myLength);
90
-        stMemFreeAligned(myBuffer);
91
+        if(myIsOwnData) {
92
+            stMemFreeAligned(myBuffer);
93
+        }
94
+        myIsOwnData = true;
95
 
96
         // update pointers of image(s) data
97
         for(StHandle<StJpegParser::Image> anImg = myImages;
98
@@ -607,6 +657,20 @@
99
     return aString;
100
 }
101
 
102
+bool StJpegParser::Image::get360PanoMakerNote(bool& theIsStereo) const {
103
+    StExifDir::Query aQuery(StExifDir::DType_General, StExifTags::Image_MakerNote, StExifEntry::FMT_STRING);
104
+    if(!StExifDir::findEntry(Exif, aQuery)) {
105
+        return false;
106
+    } else if(::strncmp((char* )aQuery.Entry.ValuePtr, "360Stereo", 9) == 0) {
107
+        theIsStereo = true;
108
+        return true;
109
+    } else if(::strncmp((char* )aQuery.Entry.ValuePtr, "360Mono", 7) == 0) {
110
+        theIsStereo = false;
111
+        return true;
112
+    }
113
+    return false;
114
+}
115
+
116
 bool StJpegParser::Image::getParallax(double& theParallax) const {
117
     StExifDir::Query aQuery(StExifDir::DType_MakerFuji, StExifTags::Fuji_Parallax);
118
     if(!StExifDir::findEntry(Exif, aQuery)
119
sview-17_04.tar.gz/StShared/StLogger.ObjC.mm -> sview-20_08.tar.gz/StShared/StLogger.ObjC.mm Changed
42
 
1
@@ -22,7 +22,9 @@
2
     StLogger::GetDefault().write(theMessage, StLogger::ST_INFO);
3
     StCocoaLocalPool aLocalPool;
4
     NSString* aMessage = [NSString stringWithUTF8String: theMessage.toCString()];
5
+ST_DISABLE_DEPRECATION_WARNINGS
6
     NSRunAlertPanel(@"Info", @"%@", @"OK", nil, nil, aMessage);
7
+ST_ENABLE_DEPRECATION_WARNINGS
8
 }
9
 
10
 void StMessageBox::Warn(const StString& theMessage) {
11
@@ -32,7 +34,9 @@
12
     StLogger::GetDefault().write(theMessage, StLogger::ST_WARNING);
13
     StCocoaLocalPool aLocalPool;
14
     NSString* aMessage = [NSString stringWithUTF8String: theMessage.toCString()];
15
+ST_DISABLE_DEPRECATION_WARNINGS
16
     NSRunAlertPanel(@"Warning", @"%@", @"OK", nil, nil, aMessage);
17
+ST_ENABLE_DEPRECATION_WARNINGS
18
 }
19
 
20
 void StMessageBox::Error(const StString& theMessage) {
21
@@ -42,7 +46,9 @@
22
     StLogger::GetDefault().write(theMessage, StLogger::ST_ERROR);
23
     StCocoaLocalPool aLocalPool;
24
     NSString* aMessage = [NSString stringWithUTF8String: theMessage.toCString()];
25
+ST_DISABLE_DEPRECATION_WARNINGS
26
     NSRunAlertPanel(@"Error", @"%@", @"OK", nil, nil, aMessage);
27
+ST_ENABLE_DEPRECATION_WARNINGS
28
 }
29
 
30
 bool StMessageBox::Question(const StString& theMessage) {
31
@@ -51,8 +57,10 @@
32
     }
33
     StCocoaLocalPool aLocalPool;
34
     NSString* aMessage = [NSString stringWithUTF8String: theMessage.toCString()];
35
+ST_DISABLE_DEPRECATION_WARNINGS
36
     int aResult = NSRunAlertPanel(@"Question", @"%@", @"Yes", @"No", nil, aMessage);
37
     return aResult == NSAlertDefaultReturn;
38
+ST_ENABLE_DEPRECATION_WARNINGS
39
 }
40
 
41
 #endif // __APPLE__
42
sview-17_04.tar.gz/StShared/StPlayList.cpp -> sview-20_08.tar.gz/StShared/StPlayList.cpp Changed
25
 
1
@@ -587,9 +587,9 @@
2
         }
3
 
4
         if(myCurrent != NULL) {
5
-            if(aRemItem->getPlayedFlag() != aPlayedFlag) {
6
+            if(myCurrent->getPlayedFlag() != aPlayedFlag) {
7
                 // the item has not been played yet - mark it as such
8
-                aRemItem->setPlayedFlag(aPlayedFlag);
9
+                myCurrent->setPlayedFlag(aPlayedFlag);
10
             } else {
11
                 // one played item has been removed
12
                 --myPlayedCount;
13
@@ -1120,7 +1120,10 @@
14
         }
15
     } else {
16
         // not a filesystem element - probably url or invalid path
17
-        StFileNode* aFileNode = new StFileNode(thePath, &myFoldersRoot);
18
+        StFolder* aSubFolder = new StFolder(stCString(""), &myFoldersRoot);
19
+        myFoldersRoot.add(aSubFolder);
20
+
21
+        StFileNode* aFileNode = new StFileNode(thePath, aSubFolder);
22
         myFoldersRoot.add(aFileNode);
23
         addRecentFile(*aFileNode); // append to recent files list
24
         addPlayItem(new StPlayItem(aFileNode, myDefStParams));
25
sview-17_04.tar.gz/StShared/StProcess.cpp -> sview-20_08.tar.gz/StShared/StProcess.cpp Changed
13
 
1
@@ -35,7 +35,11 @@
2
     static const StString STCORE_NAME = StString("StCore")    + ST_DLIB_SUFFIX;
3
 #else
4
     static const StString STCORE_NAME = StString("libStCore") + ST_DLIB_SUFFIX;
5
+#ifndef APP_PREFIX
6
     static const StString ST_DEFAULT_PATH = "/usr/share/sView/";
7
+#else
8
+    static const StString ST_DEFAULT_PATH = APP_PREFIX"/share/sView/";
9
+#endif
10
 #endif
11
 
12
     inline bool isValidStSharePath(const StString& thePath) {
13
sview-17_04.tar.gz/StShared/StRawFile.cpp -> sview-20_08.tar.gz/StShared/StRawFile.cpp Changed
38
 
1
@@ -42,7 +42,8 @@
2
   myFileHandle(NULL),
3
   myBuffer(NULL),
4
   myBuffSize(0),
5
-  myLength(0) {
6
+  myLength(0),
7
+  myIsOwnData(false) {
8
     //
9
 }
10
 
11
@@ -119,13 +120,25 @@
12
         return;
13
     }
14
     freeBuffer();
15
+    myIsOwnData = true;
16
     myBuffSize = theDataSize;
17
     myBuffer = stMemAllocAligned<stUByte_t*>(myBuffSize + 1);
18
     myBuffer[myBuffSize] = '\0'; // just for safe
19
 }
20
 
21
+void StRawFile::wrapBuffer(stUByte_t* theBuffer,
22
+                           size_t theDataSize) {
23
+    freeBuffer();
24
+    myIsOwnData = false;
25
+    myBuffSize = theDataSize;
26
+    myBuffer = theBuffer;
27
+}
28
+
29
 void StRawFile::freeBuffer() {
30
-    stMemFreeAligned(myBuffer);
31
+    if(myIsOwnData) {
32
+        stMemFreeAligned(myBuffer);
33
+        myIsOwnData = false;
34
+    }
35
     myBuffer = NULL;
36
     myBuffSize = 0;
37
 }
38
sview-17_04.tar.gz/StShared/StResourceManager.cpp -> sview-20_08.tar.gz/StShared/StResourceManager.cpp Changed
76
 
1
@@ -80,10 +80,13 @@
2
 
3
 StResourceManager::StResourceManager(const StString& theAppName)
4
 : myAppName(theAppName),
5
-  myUserHomeFolder(StProcess::getEnv(StString("HOME")) + SYS_FS_SPLITTER),
6
+  myUserHomeFolder(StProcess::getEnv(StString("HOME"))),
7
   myResFolder(StProcess::getStShareFolder()),
8
   myLang("en") {
9
-
10
+#if !defined(__ANDROID__)
11
+    myFolders[FolderId_Documents] = myUserHomeFolder;
12
+#endif
13
+    myUserHomeFolder += SYS_FS_SPLITTER;
14
 #if defined(_WIN32)
15
     StString anAppDataLocal, anAppDataLocalLow, anAppDataRoam;
16
     wchar_t* aPath = NULL;
17
@@ -101,6 +104,7 @@
18
     }
19
     if(::SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &aPath) == S_OK) {
20
         myUserHomeFolder.fromUnicode(aPath);
21
+        myFolders[FolderId_Documents] = myUserHomeFolder;
22
         myUserHomeFolder += "\\";
23
         ::CoTaskMemFree(aPath);
24
     }
25
@@ -158,20 +162,32 @@
26
     StFolder::createFolder(myUserHomeFolder + "Library/Caches");
27
 #else
28
     // Linux world
29
-    myUserDataFolder = myUserHomeFolder + ".local/share/" + myAppName + "/";
30
-    mySettingsFolder = myUserHomeFolder + ".config/"      + myAppName + "/";
31
-    myCacheFolder    = myUserHomeFolder + ".cache/"       + myAppName + "/";
32
+    myUserDataFolder = StProcess::getEnv(StString("XDG_DATA_HOME"));
33
+    if(myUserDataFolder.isEmpty()) {
34
+        myUserDataFolder = myUserHomeFolder + ".local/share";
35
+        StFolder::createFolder(myUserHomeFolder + ".local");
36
+        StFolder::createFolder(myUserDataFolder);
37
+    }
38
+    myUserDataFolder = myUserDataFolder + "/" + myAppName + "/";
39
+
40
+    mySettingsFolder = StProcess::getEnv(StString("XDG_CONFIG_HOME"));
41
+    if(mySettingsFolder.isEmpty()) {
42
+        mySettingsFolder = myUserHomeFolder + ".config";
43
+        StFolder::createFolder(mySettingsFolder);
44
+    }
45
+    mySettingsFolder = mySettingsFolder + "/" + myAppName + "/";
46
+
47
+    myCacheFolder = StProcess::getEnv(StString("XDG_CACHE_HOME"));
48
+    if(myCacheFolder.isEmpty()) {
49
+        myCacheFolder = myUserHomeFolder + ".cache";
50
+        StFolder::createFolder(myCacheFolder);
51
+    }
52
+    myCacheFolder = myCacheFolder + "/" + myAppName + "/";
53
 
54
     myFolders[FolderId_Downloads] = myUserHomeFolder + "Downloads";
55
     myFolders[FolderId_Pictures]  = myUserHomeFolder + "Pictures";
56
     myFolders[FolderId_Music]     = myUserHomeFolder + "Music";
57
     myFolders[FolderId_Videos]    = myUserHomeFolder + "Videos";
58
-
59
-    // make sure parent paths are also exist (on broken home)
60
-    StFolder::createFolder(myUserHomeFolder + ".local");
61
-    StFolder::createFolder(myUserHomeFolder + ".local/share");
62
-    StFolder::createFolder(myUserHomeFolder + ".config");
63
-    StFolder::createFolder(myUserHomeFolder + ".cache");
64
 #endif
65
 
66
     StFolder::createFolder(myUserDataFolder);
67
@@ -187,6 +203,8 @@
68
         myLang = aSysLoc.subString(0, 2);
69
     } else if(aSysLoc.isStartsWith(stCString("russian"))) {
70
         myLang = "ru";
71
+    } else if(aSysLoc.isStartsWith(stCString("spanish"))) {
72
+        myLang = "es";
73
     } else if(aSysLoc.isStartsWith(stCString("french"))) {
74
         myLang = "fr";
75
     } else if(aSysLoc.isStartsWith(stCString("german"))) {
76
sview-17_04.tar.gz/StShared/StShared.cbp -> sview-20_08.tar.gz/StShared/StShared.cbp Changed
33
 
1
@@ -304,6 +304,7 @@
2
        <Unit filename="StGLTexture.cpp" />
3
        <Unit filename="StGLTextureData.cpp" />
4
        <Unit filename="StGLTextureQueue.cpp" />
5
+       <Unit filename="StGLUVCylinder.cpp" />
6
        <Unit filename="StGLUVSphere.cpp" />
7
        <Unit filename="StGLVertexBuffer.cpp" />
8
        <Unit filename="StImage.cpp" />
9
@@ -340,6 +341,7 @@
10
        </Unit>
11
        <Unit filename="StResourceManager.cpp" />
12
        <Unit filename="StSettings.cpp" />
13
+       <Unit filename="StStbImage.cpp" />
14
        <Unit filename="StSocket.ObjC.mm">
15
            <Option compile="1" />
16
            <Option link="1" />
17
@@ -439,6 +441,7 @@
18
        <Unit filename="../include/StGLMesh/StGLMesh.h" />
19
        <Unit filename="../include/StGLMesh/StGLPrism.h" />
20
        <Unit filename="../include/StGLMesh/StGLQuads.h" />
21
+       <Unit filename="../include/StGLMesh/StGLUVCylinder.h" />
22
        <Unit filename="../include/StGLMesh/StGLUVSphere.h" />
23
        <Unit filename="../include/StGLStereo/StFormatEnum.h" />
24
        <Unit filename="../include/StGLStereo/StGLProjCamera.h" />
25
@@ -457,6 +460,7 @@
26
        <Unit filename="../include/StImage/StImagePlane.h" />
27
        <Unit filename="../include/StImage/StJpegParser.h" />
28
        <Unit filename="../include/StImage/StPixelRGB.h" />
29
+       <Unit filename="../include/StImage/StStbImage.h" />
30
        <Unit filename="../include/StImage/StWebPImage.h" />
31
        <Unit filename="../include/StLibrary.h" />
32
        <Unit filename="../include/StSettings/StEnumParam.h" />
33
sview-17_04.tar.gz/StShared/StShared.rc -> sview-20_08.tar.gz/StShared/StShared.rc Changed
10
 
1
@@ -15,7 +15,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "sView common algorithms library\000"
4
       VALUE "FileVersion",     SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright",  "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright",  "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName",     "StShared\000"
8
       VALUE "ProductVersion",  SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite",    "www.sview.ru\000"
10
sview-17_04.tar.gz/StShared/StShared.vcxproj -> sview-20_08.tar.gz/StShared/StShared.vcxproj Changed
33
 
1
@@ -251,6 +251,7 @@
2
     <ClCompile Include="StGLTexture.cpp" />
3
     <ClCompile Include="StGLTextureData.cpp" />
4
     <ClCompile Include="StGLTextureQueue.cpp" />
5
+    <ClCompile Include="StGLUVCylinder.cpp" />
6
     <ClCompile Include="StGLUVSphere.cpp" />
7
     <ClCompile Include="StGLVertexBuffer.cpp" />
8
     <ClCompile Include="StImage.cpp" />
9
@@ -271,6 +272,7 @@
10
     <ClCompile Include="StRegisterImpl.cpp" />
11
     <ClCompile Include="StResourceManager.cpp" />
12
     <ClCompile Include="StSettings.cpp" />
13
+    <ClCompile Include="StStbImage.cpp" />
14
     <ClCompile Include="StDictionary.cpp" />
15
     <ClCompile Include="StThread.cpp" />
16
     <ClCompile Include="StTranslations.cpp" />
17
@@ -352,6 +354,7 @@
18
     <ClInclude Include="..\include\StGLMesh\StGLMesh.h" />
19
     <ClInclude Include="..\include\StGLMesh\StGLPrism.h" />
20
     <ClInclude Include="..\include\StGLMesh\StGLQuads.h" />
21
+    <ClInclude Include="..\include\StGLMesh\StGLUVCylinder.h" />
22
     <ClInclude Include="..\include\StGLMesh\StGLUVSphere.h" />
23
     <ClInclude Include="..\include\StGLStereo\StFormatEnum.h" />
24
     <ClInclude Include="..\include\StGLStereo\StGLProjCamera.h" />
25
@@ -370,6 +373,7 @@
26
     <ClInclude Include="..\include\StImage\StImagePlane.h" />
27
     <ClInclude Include="..\include\StImage\StJpegParser.h" />
28
     <ClInclude Include="..\include\StImage\StPixelRGB.h" />
29
+    <ClInclude Include="..\include\StImage\StStbImage.h" />
30
     <ClInclude Include="..\include\StImage\StWebPImage.h" />
31
     <ClInclude Include="..\include\StSettings\StEnumParam.h" />
32
     <ClInclude Include="..\include\StSettings\StFloat32Param.h  " />
33
sview-20_08.tar.gz/StShared/StStbImage.cpp Added
149
 
1
@@ -0,0 +1,147 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#include <StImage/StStbImage.h>
11
+
12
+#include <StStrings/StLogger.h>
13
+#include <StThreads/StMutex.h>
14
+#include <StFile/StFileNode.h>
15
+
16
+//#define ST_HAVE_STB_IMAGE
17
+
18
+#ifdef ST_HAVE_STB_IMAGE
19
+    #define STB_IMAGE_IMPLEMENTATION
20
+    //#define STB_IMAGE_RESIZE_IMPLEMENTATION
21
+    //#define STB_IMAGE_WRITE_IMPLEMENTATION
22
+    #define STBI_WINDOWS_UTF8
23
+    #include <stb_image.h>
24
+    //#include <stb_image_resize.h>
25
+    //#include <stb_image_write.h>
26
+
27
+namespace {
28
+
29
+    static StImagePlane::ImgFormat convertFromStbFormat(int theChannels, bool theIsHDR) {
30
+        switch(theChannels) {
31
+            case STBI_grey:       return theIsHDR ? StImagePlane::ImgGrayF : StImagePlane::ImgGray;
32
+            case STBI_grey_alpha: return StImagePlane::ImgUNKNOWN;
33
+            case STBI_rgb:        return theIsHDR ? StImagePlane::ImgRGBF  : StImagePlane::ImgRGB;
34
+            case STBI_rgb_alpha:  return theIsHDR ? StImagePlane::ImgRGBAF : StImagePlane::ImgRGBA;
35
+        }
36
+        return StImagePlane::ImgUNKNOWN;
37
+    }
38
+
39
+}
40
+
41
+#endif
42
+
43
+bool StStbImage::init() {
44
+#ifdef ST_HAVE_STB_IMAGE
45
+    return true;
46
+#else
47
+    return false;
48
+#endif
49
+}
50
+
51
+StStbImage::StStbImage()
52
+: myStbImage(NULL) {
53
+    StStbImage::init();
54
+}
55
+
56
+StStbImage::~StStbImage() {
57
+    close();
58
+}
59
+
60
+void StStbImage::close() {
61
+    if(myStbImage != NULL) {
62
+    #ifdef ST_HAVE_STB_IMAGE
63
+        stbi_image_free(myStbImage);
64
+    #endif
65
+        myStbImage = NULL;
66
+    }
67
+}
68
+
69
+bool StStbImage::loadExtra(const StString& theFilePath,
70
+                           ImageType       theImageType,
71
+                           uint8_t*        theDataPtr,
72
+                           int             theDataSize,
73
+                           bool            theIsOnlyRGB) {
74
+    (void )theIsOnlyRGB;
75
+    if(!StStbImage::init()) {
76
+        setState("STB library is not initialized");
77
+        return false;
78
+    }
79
+
80
+    // reset current data
81
+    StImage::nullify();
82
+    setState();
83
+    close();
84
+
85
+#ifdef ST_HAVE_STB_IMAGE
86
+    bool isHdr = false;
87
+    int aWidth = 0, aHeight = 0, aChannels = 0;
88
+    //stbi_set_flip_vertically_on_load(true);
89
+    if(theDataPtr != NULL) {
90
+        (void )theImageType;
91
+        //stbi_info_from_memory();
92
+        isHdr = stbi_is_hdr_from_memory((unsigned char*)theDataPtr, theDataSize) != 0;
93
+        if(isHdr) {
94
+            //myStbImage = stbi_load_16_from_memory((unsigned char*)theDataPtr, theDataSize, &aWidth, &aHeight, &aChannels, STBI_default);
95
+            myStbImage = stbi_loadf_from_memory((unsigned char*)theDataPtr, theDataSize, &aWidth, &aHeight, &aChannels, STBI_default);
96
+        } else {
97
+            myStbImage = stbi_load_from_memory((unsigned char*)theDataPtr, theDataSize, &aWidth, &aHeight, &aChannels, STBI_default);
98
+        }
99
+    } else {
100
+        //stbi_info();
101
+        isHdr = stbi_is_hdr(theFilePath.toCString()) != 0;
102
+        if(isHdr) {
103
+            //myStbImage = stbi_load_16(theFilePath.toCString(), &aWidth, &aHeight, &aChannels, STBI_default);
104
+            myStbImage = stbi_loadf(theFilePath.toCString(), &aWidth, &aHeight, &aChannels, STBI_default);
105
+        } else {
106
+            myStbImage = stbi_load(theFilePath.toCString(), &aWidth, &aHeight, &aChannels, STBI_default);
107
+        }
108
+    }
109
+
110
+    if(myStbImage == NULL
111
+    || aWidth  < 1
112
+    || aHeight < 1) {
113
+        //stbi_failure_reason()
114
+        setState("STB library, unable to load image");
115
+        close();
116
+        return false;
117
+    }
118
+
119
+    StImagePlane::ImgFormat anImgFormat = convertFromStbFormat(aChannels, isHdr);
120
+    if(anImgFormat == StImagePlane::ImgUNKNOWN) {
121
+        setState("STB library, unknown pixel format");
122
+        close();
123
+        return false;
124
+    }
125
+
126
+    setColorModelPacked(anImgFormat);
127
+    changePlane(0).initWrapper(anImgFormat, (unsigned char* )myStbImage, aWidth, aHeight);
128
+
129
+    // set debug information
130
+    StString aDummy, aFileName;
131
+    StFileNode::getFolderAndFile(theFilePath, aDummy, aFileName);
132
+    setState(StString("STB library, loaded image '") + aFileName + "' " + getDescription());
133
+    return true;
134
+#else
135
+    (void )theFilePath;
136
+    (void )theImageType;
137
+    (void )theDataPtr;
138
+    (void )theDataSize;
139
+    return false;
140
+#endif
141
+}
142
+
143
+bool StStbImage::save(const StString& ,
144
+                      ImageType ,
145
+                      StFormat ) {
146
+    setState("STB library, save operation is NOT implemented");
147
+    return false;
148
+}
149
sview-17_04.tar.gz/StShared/StThread.cpp -> sview-20_08.tar.gz/StShared/StThread.cpp Changed
57
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -114,20 +114,44 @@
9
 }
10
 
11
 bool StThread::wait() {
12
+    if(!isValid()) {
13
+        return false;
14
+    }
15
+
16
 #ifdef _WIN32
17
-    return isValid() && (WaitForSingleObject((HANDLE )myThread, INFINITE) != WAIT_FAILED);
18
+    if(WaitForSingleObject((HANDLE )myThread, INFINITE) == WAIT_FAILED) {
19
+        return false;
20
+    }
21
+    CloseHandle((HANDLE )myThread);
22
+    myThread = NULL;
23
 #else
24
-    return isValid() && (pthread_join(myThread, NULL) == 0);
25
+    if(pthread_join(myThread, NULL) != 0) {
26
+        return false;
27
+    }
28
+    myHasHandle = false;
29
 #endif
30
+    return true;
31
 }
32
 
33
 bool StThread::wait(const int theTimeMilliseconds) {
34
+    if(!isValid()) {
35
+        return false;
36
+    }
37
+
38
 #ifdef _WIN32
39
-    return isValid() && (WaitForSingleObject((HANDLE )myThread, (DWORD )theTimeMilliseconds) != WAIT_TIMEOUT);
40
+    if(WaitForSingleObject((HANDLE )myThread, (DWORD )theTimeMilliseconds) == WAIT_TIMEOUT) {
41
+        return false;
42
+    }
43
+    CloseHandle((HANDLE )myThread);
44
+    myThread = NULL;
45
 #else
46
     (void )theTimeMilliseconds;
47
-    return isValid() && (pthread_join(myThread, NULL) == 0);
48
+    if(pthread_join(myThread, NULL) != 0) {
49
+        return false;
50
+    }
51
+    myHasHandle = false;
52
 #endif
53
+    return true;
54
 }
55
 
56
 void StThread::kill() {
57
sview-17_04.tar.gz/StShared/StTranslations.cpp -> sview-20_08.tar.gz/StShared/StTranslations.cpp Changed
34
 
1
@@ -58,6 +58,10 @@
2
             params.language->changeValues().add("English");
3
             myLangFolderList.add("English");
4
         }
5
+        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "Spanish" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
6
+            params.language->changeValues().add("Español");
7
+            myLangFolderList.add("Spanish");
8
+        }
9
         if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "Russian" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
10
             params.language->changeValues().add("русский");
11
             myLangFolderList.add("Russian");
12
@@ -110,6 +114,12 @@
13
                 params.language->setValue(int32_t(anIdInList));
14
                 isLangSet = true;
15
             }
16
+        } else if(aLang.isEqualsIgnoreCase(stCString("es"))) {
17
+            if(myLangFolderList.contains(stCString("Spanish"), anIdInList)
18
+            || myLangFolderList.contains(stCString("Español"), anIdInList)) {
19
+                params.language->setValue(int32_t(anIdInList));
20
+                isLangSet = true;
21
+            }
22
         } else if(aLang.isEqualsIgnoreCase(stCString("fr"))) {
23
             if(myLangFolderList.contains(stCString("French"),   anIdInList)
24
             || myLangFolderList.contains(stCString("français"), anIdInList)) {
25
@@ -170,6 +180,8 @@
26
     const StString& aLang = params.language->getValues()[theNewLang];
27
     if(aLang == stCString("русский")) {
28
         myLangCode = "rus";
29
+    } else if(aLang == stCString("Español")) {
30
+        myLangCode = "spa";
31
     } else if(aLang == stCString("français")) {
32
         myLangCode = "fre";
33
         //myLangCode = "fra";
34
sview-17_04.tar.gz/StShared/StVirtualKeys.cpp -> sview-20_08.tar.gz/StShared/StVirtualKeys.cpp Changed
28
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2013-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2013-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -202,8 +202,8 @@
9
         stCString(","),     // ST_VK_COMMA
10
         stCString("-"),     // ST_VK_OEM_MINUS
11
         stCString("."),     // ST_VK_PERIOD
12
-        stCString(""),      // ST_VK_OEM_2
13
-        stCString(""),      // ST_VK_OEM_3
14
+        stCString("/"),     // ST_VK_SLASH
15
+        stCString("~"),     // ST_VK_TILDE
16
         stCString(""),      // 193
17
         stCString(""),      // 194
18
         stCString(""),      // 195
19
@@ -317,7 +317,7 @@
20
         aStr += "Fn+";
21
     }
22
     if(aKey == 0
23
-    || aKey > 255) {
24
+    || aKey >= ST_VK_NB) {
25
         return "";
26
     }
27
     if(aKey == ST_VK_SHIFT
28
sview-17_04.tar.gz/StShared/StWebPImage.cpp -> sview-20_08.tar.gz/StShared/StWebPImage.cpp Changed
37
 
1
@@ -28,6 +28,7 @@
2
         VP8_STATUS_NOT_ENOUGH_DATA
3
     } VP8StatusCode;
4
 
5
+#ifdef ST_HAVE_WEBP
6
     static const char* const WebPStatusMessages[] = {
7
         "OK",                  // VP8_STATUS_OK
8
         "OUT_OF_MEMORY",       // VP8_STATUS_OUT_OF_MEMORY
9
@@ -38,6 +39,7 @@
10
         "USER_ABORT",          // VP8_STATUS_USER_ABORT
11
         "NOT_ENOUGH_DATA"      // VP8_STATUS_NOT_ENOUGH_DATA
12
     };
13
+#endif
14
 
15
     extern int WebPInitDecoderConfigInternal(StWebPImage::WebPDecoderConfig* theConfig, int theVersion);
16
 
17
@@ -70,8 +72,7 @@
18
 }
19
 
20
 StWebPImage::StWebPImage()
21
-: StImageFile(),
22
-  myIsCompat(false) {
23
+: myIsCompat(false) {
24
 #ifdef ST_HAVE_WEBP
25
     myIsCompat = WebPInitDecoderConfig(&myConfig) != 0;
26
 #endif
27
@@ -86,6 +87,9 @@
28
     if(myIsCompat) {
29
         WebPFreeDecBuffer(&myConfig.output);
30
     }
31
+#else
32
+    (void )myConfig;
33
+    (void )myIsCompat;
34
 #endif
35
 }
36
 
37
sview-17_04.tar.gz/StShared/stAV.cpp -> sview-20_08.tar.gz/StShared/stAV.cpp Changed
185
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -35,7 +35,8 @@
9
     #endif
10
 #endif
11
 
12
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 30, 0))
13
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 30, 0)) \
14
+&& ((LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)) || defined(ST_LIBAV_FORK))
15
 class StFFMpegLocker {
16
 
17
         public:
18
@@ -104,11 +105,14 @@
19
 #endif
20
 const AVPixelFormat stAV::PIX_FMT::NONE       = AVPixelFormat(-1);
21
 const AVPixelFormat stAV::PIX_FMT::YUV420P    = AVPixelFormat( 0);
22
+const AVPixelFormat stAV::PIX_FMT::YUVA420P   = ST_AV_GETPIXFMT("yuva420p");
23
 const AVPixelFormat stAV::PIX_FMT::PAL8       = ST_AV_GETPIXFMT("pal8");
24
 const AVPixelFormat stAV::PIX_FMT::GRAY8      = ST_AV_GETPIXFMT("gray");
25
 const AVPixelFormat stAV::PIX_FMT::GRAY16     = ST_AV_GETPIXFMT("gray16");
26
 const AVPixelFormat stAV::PIX_FMT::YUV422P    = ST_AV_GETPIXFMT("yuv422p");
27
+const AVPixelFormat stAV::PIX_FMT::YUVA422P   = ST_AV_GETPIXFMT("yuva422p");
28
 const AVPixelFormat stAV::PIX_FMT::YUV444P    = ST_AV_GETPIXFMT("yuv444p");
29
+const AVPixelFormat stAV::PIX_FMT::YUVA444P   = ST_AV_GETPIXFMT("yuva444p");
30
 const AVPixelFormat stAV::PIX_FMT::YUV410P    = ST_AV_GETPIXFMT("yuv410p");
31
 const AVPixelFormat stAV::PIX_FMT::YUV411P    = ST_AV_GETPIXFMT("yuv411p");
32
 const AVPixelFormat stAV::PIX_FMT::YUV440P    = ST_AV_GETPIXFMT("yuv440p");
33
@@ -134,6 +138,7 @@
34
 const AVPixelFormat stAV::PIX_FMT::BGRA64     = ST_AV_GETPIXFMT("bgra64");
35
 const AVPixelFormat stAV::PIX_FMT::XYZ12      = ST_AV_GETPIXFMT("xyz12");
36
 const AVPixelFormat stAV::PIX_FMT::DXVA2_VLD  = ST_AV_GETPIXFMT("dxva2_vld");
37
+const AVPixelFormat stAV::PIX_FMT::VIDEOTOOLBOX_VLD  = ST_AV_GETPIXFMT("videotoolbox_vld");
38
 
39
 // TODO (Kirill Gavrilov#9) remove this stuff
40
 namespace {
41
@@ -154,6 +159,8 @@
42
         return stCString("none");
43
     } else if(theFrmt == stAV::PIX_FMT::YUV420P) {
44
         return stCString("yuv420p");
45
+    } else if(theFrmt == stAV::PIX_FMT::YUVA420P) {
46
+        return stCString("yuva420p");
47
     } else if(theFrmt == stAV::PIX_FMT::PAL8) {
48
         return stCString("pal8");
49
     } else if(theFrmt == stAV::PIX_FMT::GRAY8) {
50
@@ -162,8 +169,12 @@
51
         return stCString("gray16");
52
     } else if(theFrmt == stAV::PIX_FMT::YUV422P) {
53
         return stCString("yuv422p");
54
+    } else if(theFrmt == stAV::PIX_FMT::YUVA422P) {
55
+        return stCString("yuva422p");
56
     } else if(theFrmt == stAV::PIX_FMT::YUV444P) {
57
         return stCString("yuv444p");
58
+    } else if(theFrmt == stAV::PIX_FMT::YUVA444P) {
59
+        return stCString("yuva444p");
60
     } else if(theFrmt == stAV::PIX_FMT::YUV410P) {
61
         return stCString("yuv410p");
62
     } else if(theFrmt == stAV::PIX_FMT::YUV411P) {
63
@@ -263,17 +274,20 @@
64
 #endif
65
 
66
     static bool initOnce() {
67
+    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 30, 0)) \
68
+    && ((LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)) || defined(ST_LIBAV_FORK))
69
         // register own mutex to prevent multithreading errors
70
         // while using FFmpeg functions
71
-    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 30, 0))
72
         stFFMpegLocker.init();
73
-    #else
74
-        #warning Ancient FFmpeg used, initialization performed in thread-unsafe manner!
75
     #endif
76
+
77
+    #if(LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)) || defined(ST_LIBAV_FORK)
78
         // Notice, this call is absolutely not thread safe!
79
         // you should never call it first time from concurrent threads.
80
         // But after first initialization is done this is safe to call it anyhow
81
         av_register_all();
82
+    #endif
83
+
84
     #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 13, 0))
85
         avformat_network_init();
86
     #endif
87
@@ -301,10 +315,13 @@
88
 
89
 bool stAV::isFormatYUVPlanar(const AVCodecContext* theCtx) {
90
     return theCtx->pix_fmt == stAV::PIX_FMT::YUV420P
91
+        || theCtx->pix_fmt == stAV::PIX_FMT::YUVA420P
92
         || theCtx->pix_fmt == stAV::PIX_FMT::YUVJ420P
93
         || theCtx->pix_fmt == stAV::PIX_FMT::YUV422P
94
+        || theCtx->pix_fmt == stAV::PIX_FMT::YUVA422P
95
         || theCtx->pix_fmt == stAV::PIX_FMT::YUVJ422P
96
         || theCtx->pix_fmt == stAV::PIX_FMT::YUV444P
97
+        || theCtx->pix_fmt == stAV::PIX_FMT::YUVA444P
98
         || theCtx->pix_fmt == stAV::PIX_FMT::YUVJ444P
99
         || theCtx->pix_fmt == stAV::PIX_FMT::YUV440P
100
         || theCtx->pix_fmt == stAV::PIX_FMT::YUVJ440P
101
@@ -328,6 +345,7 @@
102
     if(thePixFmt == stAV::PIX_FMT::NONE) {
103
         return false;
104
     } else if(thePixFmt == stAV::PIX_FMT::YUV420P
105
+           || thePixFmt == stAV::PIX_FMT::YUVA420P
106
            || thePixFmt == stAV::PIX_FMT::YUVJ420P
107
            || thePixFmt == stAV::PIX_FMT::YUV420P9
108
            || thePixFmt == stAV::PIX_FMT::YUV420P10
109
@@ -337,7 +355,9 @@
110
         theDims.widthU  = theDims.widthV  = theDims.widthY  / 2;
111
         theDims.heightU = theDims.heightV = theDims.heightY / 2;
112
         theDims.isFullScale = (thePixFmt == stAV::PIX_FMT::YUVJ420P);
113
+        theDims.hasAlpha = thePixFmt == stAV::PIX_FMT::YUVA420P;
114
     } else if(thePixFmt == stAV::PIX_FMT::YUV422P
115
+           || thePixFmt == stAV::PIX_FMT::YUVA422P
116
            || thePixFmt == stAV::PIX_FMT::YUVJ422P
117
            || thePixFmt == stAV::PIX_FMT::YUV422P9
118
            || thePixFmt == stAV::PIX_FMT::YUV422P10
119
@@ -346,7 +366,9 @@
120
         theDims.heightY = theDims.heightU = theDims.heightV = theHeight;
121
         theDims.widthU  = theDims.widthV  = theDims.widthY  / 2;
122
         theDims.isFullScale = (thePixFmt == stAV::PIX_FMT::YUVJ422P);
123
+        theDims.hasAlpha = false;
124
     } else if(thePixFmt == stAV::PIX_FMT::YUV444P
125
+           || thePixFmt == stAV::PIX_FMT::YUVA444P
126
            || thePixFmt == stAV::PIX_FMT::YUVJ444P
127
            || thePixFmt == stAV::PIX_FMT::YUV444P9
128
            || thePixFmt == stAV::PIX_FMT::YUV444P10
129
@@ -354,23 +376,27 @@
130
         theDims.widthY  = theDims.widthU  = theDims.widthV  = theWidth;
131
         theDims.heightY = theDims.heightU = theDims.heightV = theHeight;
132
         theDims.isFullScale = (thePixFmt == stAV::PIX_FMT::YUVJ444P);
133
+        theDims.hasAlpha = false;
134
     } else if(thePixFmt == stAV::PIX_FMT::YUV440P
135
            || thePixFmt == stAV::PIX_FMT::YUVJ440P) {
136
         theDims.widthY  = theDims.widthU  = theDims.widthV  = theWidth;
137
         theDims.heightY = theHeight;
138
         theDims.heightU = theDims.heightV = theDims.heightY / 2;
139
         theDims.isFullScale = (thePixFmt == stAV::PIX_FMT::YUVJ440P);
140
+        theDims.hasAlpha = false;
141
     } else if(thePixFmt == stAV::PIX_FMT::YUV411P) {
142
         theDims.widthY  = theDims.widthU  = theDims.widthV  = theWidth;
143
         theDims.heightY = theDims.heightU = theDims.heightV = theHeight;
144
         theDims.widthU  = theDims.widthV  = theDims.widthY  / 4;
145
         theDims.isFullScale = false;
146
+        theDims.hasAlpha = false;
147
     } else if(thePixFmt == stAV::PIX_FMT::YUV410P) {
148
         theDims.widthY  = theDims.widthU  = theDims.widthV  = theWidth;
149
         theDims.heightY = theHeight;
150
         theDims.widthU  = theDims.widthV  = theDims.widthY  / 4;
151
         theDims.heightU = theDims.heightV = theDims.heightY / 4;
152
         theDims.isFullScale = false;
153
+        theDims.hasAlpha = false;
154
     } else {
155
         return false;
156
     }
157
@@ -583,7 +609,9 @@
158
 }
159
 
160
 stAV::meta::Dict* stAV::meta::getFrameMetadata(AVFrame* theFrame) {
161
-#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 38, 100)) && !defined(ST_LIBAV_FORK)
162
+#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 81, 102)) && !defined(ST_LIBAV_FORK)
163
+    return theFrame->metadata;
164
+#elif(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 38, 100)) && !defined(ST_LIBAV_FORK)
165
     return av_frame_get_metadata(theFrame);
166
 #else
167
     return NULL;
168
@@ -619,6 +647,16 @@
169
 #endif
170
 }
171
 
172
+bool stAV::isEnabledInputProtocol(const StString& theProtocol) {
173
+    void* anOpaque = NULL;
174
+    for(const char* aName = avio_enum_protocols(&anOpaque, 0); aName != NULL; aName = avio_enum_protocols(&anOpaque, 0)) {
175
+        if(stAreEqual(theProtocol.toCString(), aName, theProtocol.Size + 1)) {
176
+            return true;
177
+        }
178
+    }
179
+    return false;
180
+}
181
+
182
 StString stAV::getVersionInfo() {
183
 #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 0))
184
     return av_version_info();
185
sview-17_04.tar.gz/contentiousIntegration/build_sview_android.sh -> sview-20_08.tar.gz/contentiousIntegration/build_sview_android.sh Changed
8
 
1
@@ -21,4 +21,5 @@
2
 
3
 # perform building itself
4
 make --directory=$aScriptPath/.. clean
5
-make --directory=$aScriptPath/.. -j $aNbJobs android ANDROID_NDK=$SVIEW_NDK FFMPEG_ROOT=$SVIEW_FFMPEG FREETYPE_ROOT=$SVIEW_FREETYPE OPENAL_ROOT=$SVIEW_OPENAL LIBCONFIG_ROOT=$SVIEW_LIBCONFIG
6
+make --directory=$aScriptPath/.. -j $aNbJobs android ANDROID_NDK=$SVIEW_NDK ANDROID_BUILD_TOOLS=$SVIEW_BUILD_TOOLS ANDROID_PLATFORM=$SVIEW_PLATFORM \
7
+  FFMPEG_ROOT=$SVIEW_FFMPEG FREETYPE_ROOT=$SVIEW_FREETYPE OPENAL_ROOT=$SVIEW_OPENAL LIBCONFIG_ROOT=$SVIEW_LIBCONFIG WERROR_LEVEL=1
8
sview-17_04.tar.gz/contentiousIntegration/build_sview_linux.sh -> sview-20_08.tar.gz/contentiousIntegration/build_sview_linux.sh Changed
7
 
1
@@ -10,4 +10,4 @@
2
 
3
 # perform building itself
4
 make --directory=$aScriptPath/.. clean
5
-make --directory=$aScriptPath/.. -j $aNbJobs
6
+make --directory=$aScriptPath/.. -j $aNbJobs WERROR_LEVEL=1
7
sview-17_04.tar.gz/contentiousIntegration/build_sview_osx.sh -> sview-20_08.tar.gz/contentiousIntegration/build_sview_osx.sh Changed
7
 
1
@@ -10,4 +10,4 @@
2
 
3
 # perform building itself
4
 make --directory=$aScriptPath/.. clean
5
-make --directory=$aScriptPath/.. -j $aNbJobs
6
+make --directory=$aScriptPath/.. -j $aNbJobs WERROR_LEVEL=1
7
sview-17_04.tar.gz/copy_res.bat -> sview-20_08.tar.gz/copy_res.bat Changed
17
 
1
@@ -6,6 +6,7 @@
2
 chcp 65001
3
 
4
 if not exist "%TARGET_OUTPUT_DIR%lang\English"  mkdir "%TARGET_OUTPUT_DIR%lang\English"
5
+if not exist "%TARGET_OUTPUT_DIR%lang\Español"  mkdir "%TARGET_OUTPUT_DIR%lang\Español"
6
 if not exist "%TARGET_OUTPUT_DIR%lang\русский"  mkdir "%TARGET_OUTPUT_DIR%lang\русский"
7
 if not exist "%TARGET_OUTPUT_DIR%lang\français" mkdir "%TARGET_OUTPUT_DIR%lang\français"
8
 if not exist "%TARGET_OUTPUT_DIR%lang\Deutsch"  mkdir "%TARGET_OUTPUT_DIR%lang\Deutsch"
9
@@ -14,6 +15,7 @@
10
 if not exist "%TARGET_OUTPUT_DIR%lang\Czech"    mkdir "%TARGET_OUTPUT_DIR%lang\Czech"
11
 
12
 copy /Y lang\english\* "%TARGET_OUTPUT_DIR%lang\English\"
13
+copy /Y lang\spanish\* "%TARGET_OUTPUT_DIR%lang\Español\"
14
 copy /Y lang\russian\* "%TARGET_OUTPUT_DIR%lang\русский\"
15
 copy /Y lang\french\*  "%TARGET_OUTPUT_DIR%lang\français\"
16
 copy /Y lang\german\*  "%TARGET_OUTPUT_DIR%lang\Deutsch\"
17
sview-17_04.tar.gz/copy_res.sh -> sview-20_08.tar.gz/copy_res.sh Changed
17
 
1
@@ -5,6 +5,7 @@
2
 PROJECT_NAME=$2
3
 
4
 mkdir -p "${TARGET_OUTPUT_DIR}lang/English/"
5
+mkdir -p "${TARGET_OUTPUT_DIR}lang/Español/"
6
 mkdir -p "${TARGET_OUTPUT_DIR}lang/русский/"
7
 mkdir -p "${TARGET_OUTPUT_DIR}lang/français/"
8
 mkdir -p "${TARGET_OUTPUT_DIR}lang/Deutsch/"
9
@@ -12,6 +13,7 @@
10
 mkdir -p "${TARGET_OUTPUT_DIR}lang/Korean/"
11
 mkdir -p "${TARGET_OUTPUT_DIR}lang/Czech/"
12
 cp -f -r lang/english/* "${TARGET_OUTPUT_DIR}lang/English/"
13
+cp -f -r lang/spanish/* "${TARGET_OUTPUT_DIR}lang/Español/"
14
 cp -f -r lang/russian/* "${TARGET_OUTPUT_DIR}lang/русский/"
15
 cp -f -r lang/french/*  "${TARGET_OUTPUT_DIR}lang/français/"
16
 cp -f -r lang/german/*  "${TARGET_OUTPUT_DIR}lang/Deutsch/"
17
sview-17_04.tar.gz/debian/changelog.tmpl -> sview-20_08.tar.gz/debian/changelog.tmpl Changed
55
 
1
@@ -4,6 +4,53 @@
2
 
3
  -- Kirill Gavrilov <kirill@sview.ru>  unknown_date
4
 
5
+sview (1:20.05-1~unknown_distrib) unknown_distrib; urgency=low
6
+
7
+  + Added Spanish translation files.
8
+  + Image Viewer - added trilinear texture filtering option generating mip-maps.
9
+  + Image Viewer - support 1x6 cubemap layout.
10
+  + Image Viewer - panorama is now automatically enabled for JPEG files with GPano:ProjectionType tag.
11
+  + Image Viewer - panorama is now automatically enabled for JPEG files with 360Stereo/360Mono tags (game screenshots).
12
+  + Image Viewer - support DDS-packed cubemaps.
13
+  + Movie Player - image-based subtitles size can be now adjusted.
14
+  * Movie Player - workaround subtitles seeking issues for attached SRT files.
15
+  * Movie Player - fixed ASS subtitles formatting issue on files without closure tags.
16
+  * Movie Player - added handling of image-based subtitles encoded as stereoscopic pair (side-by-side).
17
+  * Image Viewer - fixed poor quality on saving JPEG (yuv420p) image into PNG (rgb).
18
+  * Image Viewer - fixed displaying WebP images with alpha channel (yuva pixel formats).
19
+  * fontconfig library is now used to retrieve paths to system fonts on Linux.
20
+
21
+ -- Kirill Gavrilov <kirill@sview.ru>  Wed, 20 May 2020 15:25:33 +0300
22
+
23
+sview (1:19.08-2~unknown_distrib) unknown_distrib; urgency=low
24
+
25
+  + Support VR180 hemisphere and cylindrical panorama inputs.
26
+  * Minor corrections/improvements.
27
+
28
+ -- Kirill Gavrilov <kirill@sview.ru>  Sun, 04 Aug 2019 20:00:00 +0300
29
+
30
+sview (17.10-1~unknown_distrib) unknown_distrib; urgency=low
31
+
32
+  + Image Viewer - display Slideshow delay parameter in Settings dialog.
33
+  + Movie Player - add general information about the stream (bitrate, codec, PAR, DAR) in File Info dialog.
34
+  * Movie Player - fix seeking to the very beginning of the file.
35
+  * Movie Player - fix (workaround) displaying attached image within some mp3 files.
36
+  * Fix text rendering artifacts when using glyphs with kerning defined.
37
+  * Fix compilation on glibc 2.26+ (Ubuntu 17.10+)
38
+
39
+ -- Kirill Gavrilov <kirill@sview.ru>  Mon, 23 Oct 2017 22:29:34 +0300
40
+
41
+sview (17.04-1~unknown_distrib) unknown_distrib; urgency=low
42
+
43
+  + Movie Player - add audio positioning while playing spheric panorama video.
44
+  + Movie Player - handle rotation info stored within video stream.
45
+  + Image Viewer, Movie Player - add overlay control for adjusting image color
46
+  + Movie Player - add option to force HRTF mixing in OpenAL Soft.
47
+  * Fix saving PNG images when using up-to-date FFmpeg.
48
+  * Image Viewer, Movie Player - fix too slow opening File Info dialog in case of long metadata.
49
+
50
+ -- Kirill Gavrilov <kirill@sview.ru>  Sun, 16 Apr 2017 21:45:20 +0300
51
+
52
 sview (16.04-1~unknown_distrib) unknown_distrib; urgency=low
53
 
54
   + Movie Player - implement GPU-accelerated conversion of NV12 and XYZ12 formats.
55
sview-17_04.tar.gz/debian/control -> sview-20_08.tar.gz/debian/control Changed
10
 
1
@@ -2,7 +2,7 @@
2
 Section: contrib/video
3
 Priority: extra
4
 Maintainer: Kirill Gavrilov <kirill@sview.ru>
5
-Build-Depends: debhelper (>= 7.0.50~), g++ (>= 4.0), libopenal-dev, libgl1-mesa-dev | libgl-dev, libgtk2.0-dev, libxpm-dev, libavcodec-dev, libavdevice-dev, libavformat-dev, libavutil-dev, libswscale-dev, libconfig++8-dev, libconfig8-dev, libfreetype6-dev, libxpm-dev
6
+Build-Depends: debhelper (>= 7.0.50~), g++ (>= 4.0), libopenal-dev, libgl1-mesa-dev | libgl-dev, libgtk2.0-dev, libxpm-dev, libavcodec-dev, libavdevice-dev, libavformat-dev, libavutil-dev, libswscale-dev, libconfig++-dev, libfreetype6-dev, libxpm-dev
7
 Standards-Version: 3.9.1
8
 Homepage: http://www.sview.ru
9
 
10
sview-17_04.tar.gz/debian/copyright -> sview-20_08.tar.gz/debian/copyright Changed
10
 
1
@@ -3,7 +3,7 @@
2
 Source: <http://www.sview.ru>
3
 
4
 Files: *
5
-Copyright: 2008-2015 Kirill Gavrilov <kirill@sview.ru>
6
+Copyright: 2008-2020 Kirill Gavrilov <kirill@sview.ru>
7
 License: GPL-3.0+
8
 
9
 Files: debian/*
10
sview-17_04.tar.gz/distribution/build.bat -> sview-20_08.tar.gz/distribution/build.bat Changed
79
 
1
@@ -25,31 +25,18 @@
2
 
3
 if exist "%~dp0env.bat" call "%~dp0env.bat"
4
 
5
-set YEAR=%date:~-2,4%
6
-set MONTH00=%date:~-7,2%
7
-set MONTH=%date:~-7,2%
8
-set DAY=%date:~0,2%
9
-
10
-rem Remove first zero
11
-if "%MONTH%"=="01" set MONTH=1
12
-if "%MONTH%"=="02" set MONTH=2
13
-if "%MONTH%"=="03" set MONTH=3
14
-if "%MONTH%"=="04" set MONTH=4
15
-if "%MONTH%"=="05" set MONTH=5
16
-if "%MONTH%"=="06" set MONTH=6
17
-if "%MONTH%"=="07" set MONTH=7
18
-if "%MONTH%"=="08" set MONTH=8
19
-if "%MONTH%"=="09" set MONTH=9
20
-
21
-if "%DAY%"=="01" set DAY=1
22
-if "%DAY%"=="02" set DAY=2
23
-if "%DAY%"=="03" set DAY=3
24
-if "%DAY%"=="04" set DAY=4
25
-if "%DAY%"=="05" set DAY=5
26
-if "%DAY%"=="06" set DAY=6
27
-if "%DAY%"=="07" set DAY=7
28
-if "%DAY%"=="08" set DAY=8
29
-if "%DAY%"=="09" set DAY=9
30
+for /F "skip=1 delims=" %%F in ('
31
+  wmic PATH Win32_LocalTime GET Day^,Month^,Year /FORMAT:TABLE
32
+') do (
33
+  for /F "tokens=1-3" %%L in ("%%F") do (
34
+    set DAY=%%L
35
+    set DAY00=0%%L
36
+    set MONTH=%%M
37
+    set MONTH00=0%%M
38
+    set YEAR=%%N
39
+  )
40
+)
41
+set YEAR=%YEAR:~-2,4%
42
 
43
 set SVIEW_DISTR_PATH_X86=%~dp0temp\sView-win-x86
44
 set SVIEW_DISTR_PATH_AMD64=%~dp0temp\sView-win-amd64
45
@@ -87,6 +74,8 @@
46
 
47
 rem Activate experimental WebP support
48
 echo #define ST_HAVE_WEBP>> "%SVIEW_BUILD_CONF%"
49
+rem Activate notifications about sView updates available on sview.ru
50
+echo #define ST_UPDATES_CHECK>> "%SVIEW_BUILD_CONF%"
51
 
52
 rem Create configuration for InnoSetup build script
53
 echo #define SVIEW_VER      "%YEAR%.%MONTH%.%SVIEW_VER_TYPE_NUM%.%DAY%"> config.iss
54
@@ -109,9 +98,23 @@
55
 echo Perform rebuild MSVC x86
56
 rem www.codeblocks.org
57
 rem --multiple-instance
58
-start /WAIT /D "%CB_PATH%" codeblocks.exe --rebuild --target="WIN_vc_x86"   "%~dp0..\workspace.workspace"
59
+start /WAIT /D "%CB_PATH%" codeblocks.exe --rebuild --target="WIN_vc_x86" "%~dp0..\workspace.workspace"
60
+if errorlevel 1 (
61
+  move /Y ..\include\stconfig.conf.buildbak ..\include\stconfig.conf
62
+  echo Build FAILED
63
+  pause
64
+  exit /B
65
+  goto :eof
66
+)
67
 echo Perform rebuild MSVC x86_64
68
 start /WAIT /D "%CB_PATH%" codeblocks.exe --rebuild --target="WIN_vc_AMD64" "%~dp0..\workspace.workspace"
69
+if errorlevel 1 (
70
+  move /Y ..\include\stconfig.conf.buildbak ..\include\stconfig.conf
71
+  echo Build FAILED
72
+  pause
73
+  exit /B
74
+  goto :eof
75
+)
76
 
77
 rem move default config file back
78
 move /Y ..\include\stconfig.conf.buildbak ..\include\stconfig.conf
79
sview-17_04.tar.gz/distribution/build.iss -> sview-20_08.tar.gz/distribution/build.iss Changed
122
 
1
@@ -38,6 +38,7 @@
2
 SetupIconFile=media\sView_Setup.ico
3
 WizardImageFile=media\sView_WizImage.bmp
4
 WizardSmallImageFile=media\sView_WizImageSmall.bmp
5
+UninstallDisplayIcon={app}\{#SVIEW_EXE_NAME}
6
 ; Additional requirements
7
 ChangesAssociations=true
8
 ChangesEnvironment=true
9
@@ -54,6 +55,7 @@
10
 ;InfoBeforeFile: {#SVIEW_DISTR_PATH_x86}\info\ReadMeEn.rtf
11
 Name: english; MessagesFile: compiler:Default.isl;           LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
12
 Name: russian; MessagesFile: compiler:Languages\Russian.isl; LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
13
+Name: spanish; MessagesFile: compiler:Languages\Spanish.isl; LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
14
 Name: french;  MessagesFile: compiler:Languages\French.isl;  LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
15
 Name: german;  MessagesFile: compiler:Languages\German.isl;  LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
16
 Name: korean;  MessagesFile: compiler:Languages\Korean.isl;  LicenseFile: {#SVIEW_DISTR_PATH_x86}\info\license.rtf
17
@@ -63,11 +65,13 @@
18
 ; Installation types
19
 english.FullInstallation=Full Installation
20
 russian.FullInstallation=Полная установка
21
+spanish.FullInstallation=Instalación completa
22
 french.FullInstallation=Installation complète
23
 german.FullInstallation=Vollständige Installation
24
 korean.FullInstallation=전체 설치
25
 chinese.FullInstallation=全部安装
26
 english.CustomInstallation=Custom Installation
27
+spanish.CustomInstallation=Instalación personalizada
28
 russian.CustomInstallation=Выборочная установка
29
 french.CustomInstallation=Installation personnalisée
30
 german.CustomInstallation=Benutzerdefinierte Installation
31
@@ -75,53 +79,72 @@
32
 chinese.CustomInstallation=自定义安装
33
 ; Components
34
 english.StCore=Core files
35
+spanish.StCore=Archivos compartidos
36
 russian.StCore=Общие файлы
37
 german.StCore=Core-Dateien
38
 english.StBrowserPlugins=NPAPI Browser plugin (Firefox, Google Chrome, Opera,...)
39
+spanish.StBrowserPlugins=Plugin de navegador NPAPI (Firefox, Google Chrome, Opera,...)
40
 russian.StBrowserPlugins=NPAPI плагин для браузеров Firefox, Google Chrome, Opera,...
41
 english.StActiveXPlugin=ActiveX control for Internet Explorer
42
+spanish.StActiveXPlugin=Control ActiveX para Internet Explorer
43
 russian.StActiveXPlugin=ActiveX плагин для браузера Internet Explorer
44
 english.StDrawers=Media types support
45
+spanish.StDrawers=Soporte de tipos de medios
46
 russian.StDrawers=Поддержка медиа-типов
47
 english.StImageViewer=Stereoscopic Image Viewer
48
+spanish.StImageViewer=Visor de imagen estereoscópica
49
 russian.StImageViewer=Просмотр стереоизображений
50
 english.StMoviePlayer=Stereoscopic Movie Player
51
+spanish.StMoviePlayer=Reproductor de películas estereoscópicas
52
 russian.StMoviePlayer=Воспроизведение стереовидео
53
 english.StRenderers=Device support
54
+spanish.StRenderers=Soporte del dispositivo
55
 russian.StRenderers=Поддержка устройств стереовывода
56
 german.StRenderers=Geräteunterstützung
57
 english.StOutAnaglyph=Anaglyph glasses
58
+spanish.StOutAnaglyph=Gafas anaglíficas
59
 russian.StOutAnaglyph=Анаглифные очки
60
 german.StOutAnaglyph=Anaglyphenbrille
61
 english.StOutDual=Mirror Displays, Dual Projectors
62
+spanish.StOutDual=Salida espejo, Salida dual
63
 russian.StOutDual=Зеркальные системы, 2х-проекторные системы
64
 english.StOutInterlace=Interlaced Displays, DLP TV
65
+spanish.StOutInterlace=Filas entrelazadas, DLP TV
66
 russian.StOutInterlace=Чересстрочные мониторы, DLP ТВ
67
 english.StOutIZ3D=IZ3D Display
68
+spanish.StOutIZ3D=Visualización IZ3D
69
 russian.StOutIZ3D=Монитор IZ3D
70
 german.StOutIZ3D=iZ3D-Bildschirmen
71
 english.StOutPageFlip=Shutter glasses
72
+spanish.StOutPageFlip=Gafas de obturador
73
 russian.StOutPageFlip=Затворные очки
74
 german.StOutPageFlip=Shutterbrille
75
 english.StOutDistorted=Distorted output
76
+spanish.StOutDistorted=Salida distorsionada
77
 russian.StOutDistorted=Искажённый вывод
78
 ; File associations
79
 english.FileAssociations=File associations
80
+spanish.FileAssociations=Asociaciones de archivos
81
 russian.FileAssociations=Файловые ассоциации
82
 german.FileAssociations=Dateizuordnungen
83
 english.AssocStereoImages=Associate stereoscopic images with sView (*.jps; *.pns; *.mpo)
84
+spanish.AssocStereoImages=Asociar imágenes estereoscópicas con sView (*.jps; *.pns; *.mpo)
85
 russian.AssocStereoImages=Связать с sView стереоизображения (*.jps; *.pns; *.mpo)
86
 german.AssocStereoImages=Associate stereoskopische Bilder mit sView (*.jps; *.pns; *.mpo)
87
 english.AssocImages=Associate common images with sView (*.jpg; *.png; *.webp; *.bmp; *.exr; *.hdr; *.tga)
88
+spanish.AssocImages=Asociar imágenes comunes con sView (*.jpg; *.png; *.webp; *.bmp; *.exr; *.hdr; *.tga)
89
 russian.AssocImages=Связать с sView обычные изображения (*.jpg; *.png; *.webp; *.bmp; *.exr; *.hdr; *.tga)
90
 german.AssocImages=Associate normale Bilder mit sView (*.jpg; *.png; *.webp; *.bmp; *.exr; *.hdr; *.tga)
91
 english.AssocMovies=Associate video files with sView (*.avi; *.mkv; *.mk3d; *.webm; *.wmv; *.ts)
92
+spanish.AssocMovies=Asociar archivos de video con sView (*.avi; *.mkv; *.mk3d; *.webm; *.wmv; *.ts)
93
 russian.AssocMovies=Связать с sView видеофайлы (*.avi; *.mkv; *.mk3d; *.webm; *.wmv; *.ts)
94
 german.AssocMovies=Associate Videodateien mit sView (*.avi; *.mkv; *.mk3d; *.webm; *.wmv; *.ts)
95
 english.AssocMusic=Associate music files with sView (*.mp3; *.ogg; *.wav; *.flac; *.ape)
96
+spanish.AssocMusic=Asociar archivos de música con sView (*.mp3; *.ogg; *.wav; *.flac; *.ape)
97
 russian.AssocMusic=Связать с sView музыкальные файлы (*.mp3; *.ogg; *.wav; *.flac; *.ape)
98
 german.AssocMusic=Associate Musikdateien mit sView (*.mp3; *.ogg; *.wav; *.flac; *.ape)
99
 english.AssocPlaylists=Associate playlist files with sView (*.m3u)
100
+spanish.AssocPlaylists=Asociar archivos de lista de reproducción con sView (*.m3u)
101
 ; OpenAL soft
102
 english.OpenALSoft51=OpenAL soft - force 5.1 channel output
103
 russian.OpenALSoft51=OpenAL soft - force 5.1 channel output
104
@@ -258,9 +281,7 @@
105
 Name: {group}\sView - Image Viewer; Filename: {app}\amd64\{#SVIEW_EXE_NAME}; Components: StDrawers\StImageViewer; IconFilename: {app}\amd64\{#SVIEW_EXE_NAME}; Comment: "{cm:StImageViewer}";  IconIndex: 0; Parameters: "--in=image --demo=""{app}\demo.jps"""; Check: IsWin64
106
 Name: {group}\sView - Movie Player; Filename: {app}\{#SVIEW_EXE_NAME};       Components: StDrawers\StMoviePlayer; IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: "{cm:StMoviePlayer}";  IconIndex: 0; Parameters: "--in=video"; Check: not IsWin64
107
 Name: {group}\sView - Movie Player; Filename: {app}\amd64\{#SVIEW_EXE_NAME}; Components: StDrawers\StMoviePlayer; IconFilename: {app}\amd64\{#SVIEW_EXE_NAME}; Comment: "{cm:StMoviePlayer}";  IconIndex: 0; Parameters: "--in=video"; Check: IsWin64
108
-Name: {group}\Extras\sView - Failsafe;                    Filename: {app}\{#SVIEW_EXE_NAME};       Components: StDrawers\StImageViewer and StRenderers\StOutAnaglyph; IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: Failsafe sView launch; IconIndex: 0; Parameters: --out=StOutAnaglyph --in=image
109
 Name: {group}\Extras\sView - Autodetection;               Filename: {app}\{#SVIEW_EXE_NAME};       Components: StDrawers\StImageViewer; IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: Failsafe sView launch; IconIndex: 0; Parameters: --out=Auto --in=image
110
-Name: {group}\Extras\sView - Movie Player 32bit;          Filename: {app}\{#SVIEW_EXE_NAME};       Components: StDrawers\StMoviePlayer; IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: "{cm:StMoviePlayer}";  IconIndex: 0; Parameters: "--in=video";         Check: IsWin64
111
 Name: {group}\Extras\sView - Movie Player (Last File);    Filename: {app}\{#SVIEW_EXE_NAME};       Components: StDrawers\StMoviePlayer; IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: "{cm:StMoviePlayer}";  IconIndex: 0; Parameters: "--last";             Check: not IsWin64
112
 Name: {group}\Extras\sView - Movie Player (Last File);    Filename: {app}\amd64\{#SVIEW_EXE_NAME}; Components: StDrawers\StMoviePlayer; IconFilename: {app}\amd64\{#SVIEW_EXE_NAME}; Comment: "{cm:StMoviePlayer}";  IconIndex: 0; Parameters: "--last";             Check: IsWin64
113
 Name: {group}\Extras\sView - Diagnostics;                 Filename: {app}\{#SVIEW_EXE_NAME};       Components: StCore;                  IconFilename: {app}\{#SVIEW_EXE_NAME};       Comment: sView Diagnostics;     IconIndex: 0; Parameters: "--in=StDiagnostics"; Check: not IsWin64
114
@@ -286,6 +307,7 @@
115
 Root: HKCU; Subkey: SOFTWARE\sView;       ValueType: none; Flags: uninsdeletekey; Tasks: ; Languages: ; ValueData: sView 2011
116
 Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: русский;  Tasks: ; Languages: russian; Flags: uninsdeletekey
117
 Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: English;  Tasks: ; Languages: english; Flags: uninsdeletekey
118
+Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: Español;  Tasks: ; Languages: spanish; Flags: uninsdeletekey
119
 Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: français; Tasks: ; Languages: french;  Flags: uninsdeletekey
120
 Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: Deutsch;  Tasks: ; Languages: german;  Flags: uninsdeletekey
121
 Root: HKCU; Subkey: Software\sView\sView; ValueType: string; ValueName: language; ValueData: Korean;   Tasks: ; Languages: korean;  Flags: uninsdeletekey
122
sview-17_04.tar.gz/distribution/buildDebSrc_ppa.sh -> sview-20_08.tar.gz/distribution/buildDebSrc_ppa.sh Changed
55
 
1
@@ -23,14 +23,22 @@
2
 # Ubuntu 15.10     (Wily Werewolf)
3
 # Ubuntu 16.04 LTS (Xenial Xerus)
4
 # Ubuntu 16.10     (Yakkety Yak)
5
-#aDistribs=("trusty" "vivid" "wily" "xenial" "yakkety")
6
-aDistribs=("vivid" "wily" "xenial")
7
+# Ubuntu 17.04     (Zesty Zapus)
8
+# Ubuntu 17.10     (Artful Aardvark)
9
+# Ubuntu 18.04 LTS (Bionic Beaver)
10
+# Ubuntu 18.10     (Cosmic Cuttlefish)
11
+# Ubuntu 19.04     (Disco Dingo)
12
+# Ubuntu 19.10
13
+# Ubuntu 20.04 LTS (Focal Fossa)
14
+# Ubuntu 20.10     (Groovy Gorilla)
15
+aDistribs=("xenial" "bionic" "focal")
16
 
17
 # Debian
18
 #aDistribs=("stable" "unstable" "testing-proposed-updates" "experimental")
19
 
20
 # remove temporary files
21
 rm -f temp/*.build
22
+rm -f temp/*.buildinfo
23
 rm -f temp/*.changes
24
 rm -f temp/*.dsc
25
 rm -f temp/*.tar.gz
26
@@ -41,18 +49,20 @@
27
 for aDistr in "${aDistribs[@]}"
28
 do
29
   echo "Prepare source package for '$aDistr'"
30
-  sed "s/unknown_distrib/${aDistr}/g"                "debian/changelog.tmpl" > "debian/changelogtmp1"
31
-  sed "s/unknown_version/${aDebVersion}~${aDistr}/g" "debian/changelogtmp1"  > "debian/changelogtmp2"
32
-  sed "s/unknown_date/${aCurrentDate}/g"             "debian/changelogtmp2"  > "debian/changelog"
33
+  sed "s/unknown_distrib/${aDistr}/g"                  "debian/changelog.tmpl" > "debian/changelogtmp1"
34
+  sed "s/unknown_version/1:${aDebVersion}~${aDistr}/g" "debian/changelogtmp1"  > "debian/changelogtmp2"
35
+  sed "s/unknown_date/${aCurrentDate}/g"               "debian/changelogtmp2"  > "debian/changelog"
36
   rm -f debian/changelogtmp*
37
 
38
   mkdir -p ../$aDistr
39
   debuild -S
40
-  mv -f ../*.build   ../$aDistr
41
-  mv -f ../*.changes ../$aDistr
42
-  mv -f ../*.dsc     ../$aDistr
43
-  mv -f ../*.tar.gz  ../$aDistr
44
-  mv -f ../*.tar.xz  ../$aDistr
45
+  mv -f ../*.build     ../$aDistr
46
+  mv -f ../*.buildinfo ../$aDistr
47
+  mv -f ../*.changes   ../$aDistr
48
+  mv -f ../*.dsc       ../$aDistr
49
+  mv -f ../*.tar.*z    ../$aDistr
50
+  #mv -f ../*.tar.gz    ../$aDistr
51
+  #mv -f ../*.tar.xz    ../$aDistr
52
 done
53
 
54
 #for aDistr in "${aDistribs[@]}"
55
sview-17_04.tar.gz/distribution/buildMac.sh -> sview-20_08.tar.gz/distribution/buildMac.sh Changed
13
 
1
@@ -38,10 +38,7 @@
2
 cp -f ../license-gpl-3.0.txt $buildRoot/sView.app/Contents/MacOS/info/license.txt
3
 
4
 # copy sView compiled files
5
-if [ -e ../bin/MAC_gcc/build.log ]; then
6
-  mv -f ../bin/MAC_gcc/build.log $buildRoot/
7
-fi
8
-cp -f -R ../bin/MAC_gcc/sView.app/* $buildRoot/sView.app/
9
+cp -f -R ../build/sView.app/* $buildRoot/sView.app/
10
 
11
 # create symlink to Applications
12
 ln -f -s /Applications "$buildRoot/"
13
sview-20_08.tar.gz/distribution/qmake Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/distribution/qmake/.gitignore Added
6
 
1
@@ -0,0 +1,4 @@
2
+/*/*.pro
3
+/*/*/*.pro
4
+*.pro.user
5
+custom.pri
6
sview-20_08.tar.gz/distribution/qmake/custom.pri.template Added
24
 
1
@@ -0,0 +1,22 @@
2
+ST_MAKE_TARGET = android
3
+ANDROID_EABI = armeabi-v7a
4
+#ANDROID_EABI = arm64-v8a
5
+#ANDROID_EABI = x86
6
+
7
+!isEmpty(ST_MAKE_TARGET) {
8
+  ST_DEPS_ROOT = $$_PRO_FILE_PWD_/../../../3rdparty/android/build
9
+
10
+  ANDROID_NDK         = $$ST_DEPS_ROOT/android-ndk-r12b
11
+  ANDROID_BUILD_TOOLS = $$ST_DEPS_ROOT/android-build-tools-26.0.3
12
+  ANDROID_PLATFORM    = $$ST_DEPS_ROOT/android-15.jar
13
+  FFMPEG_ROOT         = $$ST_DEPS_ROOT/FFmpeg-2016-07-02-git-21ee644-arm-linux-androideabi-4.9.x-LGPL
14
+  FREETYPE_ROOT       = $$ST_DEPS_ROOT/freetype-2.6.3-android
15
+  OPENAL_ROOT         = $$ST_DEPS_ROOT/openal-soft-1.17.2-arm7
16
+  LIBCONFIG_ROOT      = $$ST_DEPS_ROOT/libconfig-1.4.9-arm7
17
+
18
+  ANDROID_KEY_GUI = 1
19
+  #ANDROID_KEYSTORE = $$ST_DEPS_ROOT/sview_debug.key
20
+  #ANDROID_KEYSTORE_PASSWORD = 1
21
+  #ANDROID_KEY = "sview android key"
22
+  #ANDROID_KEY_PASSWORD = 2
23
+}
24
sview-20_08.tar.gz/distribution/qmake/dummy.cpp Added
3
 
1
@@ -0,0 +1,1 @@
2
+int main() { return 1; }
3
sview-20_08.tar.gz/distribution/qmake/sView.pro Added
31
 
1
@@ -0,0 +1,29 @@
2
+# This is a Solution project for sView.
3
+# It is intended only for code navigation using Qt Creator, not for building project!
4
+#
5
+# To use this project, open it in Qt Creator, "Run qmake" once,
6
+# close the project and open it anew, until the list of sView modules will not appear in Projects list.
7
+# Then "Run qmake" and "Build Project" which would redirect to Makefile in sView root folder.
8
+TEMPLATE = subdirs
9
+
10
+# Iterate over Modules and generate sub-projects
11
+aSolTkList = StShared StGLWidgets StCore StOutAnaglyph StOutDual StOutInterlace StOutPageFlip StOutIZ3D StOutDistorted StImageViewer StMoviePlayer StDiagnostics StCADViewer StBrowserPlugin sview StTests
12
+for (aSolToolkit, aSolTkList) {
13
+  eval(sviewtkgen_$${aSolToolkit}.input  = $$_PRO_FILE_PWD_/sViewToolkit.pro.in)
14
+  eval(sviewtkgen_$${aSolToolkit}.output = $$_PRO_FILE_PWD_/$${aSolToolkit}/$${aSolToolkit}.pro)
15
+  eval(sviewkgen_$${aSolToolkit}.config = verbatim)
16
+  eval(QMAKE_SUBSTITUTES += sviewtkgen_$${aSolToolkit})
17
+  SUBDIRS += $${aSolToolkit}
18
+
19
+  !equals(aSolToolkit, StShared) {
20
+    #$${aSolToolkit}.depends += StShared
21
+  }
22
+}
23
+
24
+aTxtListTxt = $$files($$_PRO_FILE_PWD_/../../license-*.txt)
25
+aTxtListMd1 = $$files($$_PRO_FILE_PWD_/../../*.md)
26
+aTxtListMd2 = $$files($$_PRO_FILE_PWD_/../../docs/*.md)
27
+OTHER_FILES += $$aTxtListTxt
28
+OTHER_FILES += $$aTxtListMd1
29
+OTHER_FILES += $$aTxtListMd2
30
+OTHER_FILES += $$_PRO_FILE_PWD_/../../Makefile
31
sview-20_08.tar.gz/distribution/qmake/sViewToolkit.pro.in Added
4
 
1
@@ -0,0 +1,2 @@
2
+ST_TOOLKIT_NAME = \$\$TARGET
3
+include(../tk.pri)
4
sview-20_08.tar.gz/distribution/qmake/tk.pri Added
87
 
1
@@ -0,0 +1,85 @@
2
+# This is a project template file defining an sView Toolkit.
3
+# This project should be included with predefined ST_TOOLKIT_NAME variable.
4
+
5
+#TEMPLATE = lib
6
+TEMPLATE = aux
7
+
8
+# Disable some dummy Qt defaults
9
+QT -= core gui
10
+CONFIG -= qt app_bundle
11
+CONFIG -= debug_and_release
12
+
13
+sViewRoot = $$_PRO_FILE_PWD_/../../..
14
+DESTDIR = $$sViewRoot/build
15
+LIBS += -L$$sViewRoot/build
16
+exists(custom.pri) { include(custom.pri) }
17
+
18
+aSrcListHpp0 = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.h,     true)
19
+aSrcListHpp1 = $$files($$sViewRoot/include/$$ST_TOOLKIT_NAME/*.h)
20
+aSrcListCpp  = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.cpp,   true)
21
+aSrcListMm   = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.mm,    true)
22
+aSrcListJava = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.java,  true)
23
+aSrcListRc   = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.rc,    true)
24
+aSrcListXml  = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.xml,   true)
25
+aSrcListPlist= $$files($$sViewRoot/$$ST_TOOLKIT_NAME/*.plist, true)
26
+INCLUDEPATH += $$sViewRoot/include
27
+INCLUDEPATH += $$sViewRoot/3rdparty/include
28
+HEADERS     += $$aSrcListHpp0
29
+HEADERS     += $$aSrcListHpp1
30
+!equals(TEMPLATE, aux) {
31
+  SOURCES += $$aSrcListCpp
32
+  mac { SOURCES += $$aSrcListMm }
33
+}
34
+OTHER_FILES += $$aSrcListJava
35
+OTHER_FILES += $$aSrcListRc
36
+OTHER_FILES += $$aSrcListXml
37
+OTHER_FILES += $$aSrcListPlist
38
+
39
+aLngList = chinese czech english french german korean russian
40
+for (aLngIter, aLngList) {
41
+  aSrcListLng = $$files($$sViewRoot/$$ST_TOOLKIT_NAME/lang/$$aLngIter/*.lng)
42
+  OTHER_FILES += $$aSrcListLng
43
+}
44
+
45
+equals(ST_TOOLKIT_NAME, StShared) {
46
+  aSrcListHppX = $$files($$sViewRoot/include/*.h,true)
47
+  HEADERS += $$aSrcListHppX
48
+
49
+  DEFINES += ST_SHARED_DLL
50
+} else:equals(ST_TOOLKIT_NAME, sview) {
51
+  # Define sView executable which Qt Creator will automatically use for "Run".
52
+  # Touch dummy.cpp to force QMAKE_POST_LINK redirecting to main Makefile to be executed within each build.
53
+  TEMPLATE = app
54
+  mac {
55
+    TARGET = sView.app/Contents/MacOS/sView
56
+  } else {
57
+    TARGET = sView
58
+  }
59
+  SOURCES += $$_PRO_FILE_PWD_/../dummy.cpp
60
+  QMAKE_POST_LINK += rm $(TARGET); touch $$_PRO_FILE_PWD_/../dummy.cpp;
61
+
62
+  # Redirect clean to main Makefile.
63
+  realclean.commands = $(MAKE) --directory $$sViewRoot clean
64
+  clean.depends = realclean
65
+  QMAKE_EXTRA_TARGETS += clean realclean
66
+
67
+  # Prepare make arguments
68
+  aNbJobs = $$system(getconf _NPROCESSORS_ONLN)
69
+  ST_MAKE_ARGS = -j$$aNbJobs
70
+  ST_DEBUG = 0
71
+  CONFIG(debug, debug|release) { ST_DEBUG = 1 }
72
+
73
+  #ST_MAKE_TARGET = android
74
+  !isEmpty(ST_MAKE_TARGET) { ST_MAKE_ARGS += $$ST_MAKE_TARGET }
75
+  aMakeEnvList = ST_DEBUG ANDROID_NDK ANDROID_BUILD_TOOLS ANDROID_PLATFORM ANDROID_EABI FFMPEG_ROOT FREETYPE_ROOT OPENAL_ROOT LIBCONFIG_ROOT ANDROID_KEY_GUI ANDROID_KEYSTORE ANDROID_KEYSTORE_PASSWORD ANDROID_KEY ANDROID_KEY_PASSWORD
76
+  for (aMakeEnvIter, aMakeEnvList) {
77
+    !isEmpty($${aMakeEnvIter}) { ST_MAKE_ARGS += $${aMakeEnvIter}=$$val_escape($${aMakeEnvIter}) }
78
+  }
79
+
80
+  # Redirect build to main Makefile.
81
+  QMAKE_POST_LINK   += $(MAKE) --directory $$sViewRoot $$ST_MAKE_ARGS;
82
+  #realbuild.commands = $(MAKE) --directory $$sViewRoot $$ST_MAKE_ARGS
83
+  #realbuild.target   = realbuild
84
+  #QMAKE_EXTRA_TARGETS += realbuild
85
+  #POST_TARGETDEPS     += realbuild
86
+}
87
sview-17_04.tar.gz/docs/INSTALL.md -> sview-20_08.tar.gz/docs/INSTALL.md Changed
16
 
1
@@ -38,6 +38,14 @@
2
 yum install ffmpeg-devel
3
 ~~~~~
4
 
5
+ALT Linux:
6
+~~~~~
7
+apt-get install \
8
+  gcc8-c++ gcc-c++ libGLU-devel libgtk+2-devel libXrandr-devel libfreetype-devel \
9
+  libopenal-devel libconfig-devel libconfig-c++-devel libXpm-devel libwebp-devel \
10
+  libavcodec-devel libavdevice-devel libavformat-devel libavutil-devel libswscale-devel
11
+~~~~~
12
+
13
 On Windows and macOS please refer to official documentation for each project.
14
 Notice that DevIL and FreeImage libraries are optional and are not required for building sView
15
 (libraries are loaded dynamically if available).
16
sview-17_04.tar.gz/include/StAV/StAVFrame.h -> sview-20_08.tar.gz/include/StAV/StAVFrame.h Changed
13
 
1
@@ -61,6 +61,11 @@
2
         return Frame->linesize[thePlaneId];
3
     }
4
 
5
+    /**
6
+     * @return frame timestamp estimated using various heuristics, in stream time base
7
+     */
8
+    ST_CPPEXPORT int64_t getBestEffortTimestamp() const;
9
+
10
         public:
11
 
12
     AVFrame* Frame;
13
sview-20_08.tar.gz/include/StAV/StAVIOJniHttpContext.h Added
87
 
1
@@ -0,0 +1,85 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#ifndef __StAVIOJniHttpContext_h_
11
+#define __StAVIOJniHttpContext_h_
12
+
13
+#include <StJNI/StJNIEnv.h>
14
+#include <StAV/StAVIOContext.h>
15
+
16
+/**
17
+ * Custom AVIO context for reading http/https file using JNI
18
+ * (java.net.URLConnection and java.nio.channels.ReadableByteChannel classes).
19
+ * The main purpose of this class is providing a fallback https protocol support
20
+ * in case when FFmpeg has been built without this support.
21
+ */
22
+class StAVIOJniHttpContext : public StAVIOContext {
23
+
24
+        public:
25
+
26
+    /**
27
+     * Empty constructor.
28
+     * WARNING! av_jni_get_java_vm() will be used to attach current thread to JavaVM and initialize pointers.
29
+     * Therefore, JavaVM should be set to FFmpeg beforehand, and this context should be used only within the same working thread.
30
+     */
31
+    ST_CPPEXPORT StAVIOJniHttpContext();
32
+
33
+    /**
34
+     * Destructor. Closes open stream and detaches current thread from JavaVM.
35
+     */
36
+    ST_CPPEXPORT virtual ~StAVIOJniHttpContext();
37
+
38
+    /**
39
+     * Close the file.
40
+     */
41
+    ST_CPPEXPORT void close();
42
+
43
+    /**
44
+     * Open specified URL.
45
+     */
46
+    ST_CPPEXPORT bool open(const StString& theUrl);
47
+
48
+    /**
49
+     * Read from the file.
50
+     */
51
+    ST_CPPEXPORT virtual int read(uint8_t* theBuf,
52
+                                  int      theBufSize) ST_ATTR_OVERRIDE;
53
+
54
+    /**
55
+     * Writing is not supported.
56
+     */
57
+    ST_LOCAL virtual int write(uint8_t* , int ) ST_ATTR_OVERRIDE { return -1; }
58
+
59
+    /**
60
+     * Seek within the file.
61
+     */
62
+    ST_CPPEXPORT virtual int64_t seek(int64_t theOffset,
63
+                                      int     theWhence) ST_ATTR_OVERRIDE;
64
+
65
+        private:
66
+
67
+    /**
68
+     * (Re)open HTTPS stream at specific offset.
69
+     */
70
+    bool reopenReadChannel(int64_t theOffset);
71
+    struct FunctionTable;
72
+
73
+        protected:
74
+
75
+    FunctionTable* myFunctions; //!< JNI function table
76
+    StJNIEnv myJEnv;        //!< JavaVM environment
77
+    StString myUrl;         //!< opened URL
78
+    void*    myReadChannel; //!< pointer to java.nio.channels.ReadableByteChannel
79
+    int64_t  myContentLen;  //!< file length
80
+    int64_t  myPosition;    //!< current position within the stream
81
+
82
+};
83
+
84
+ST_DEFINE_HANDLE(StAVIOJniHttpContext, StAVIOContext);
85
+
86
+#endif // __StAVIOJniHttpContext_h_
87
sview-17_04.tar.gz/include/StAV/StAVImage.h -> sview-20_08.tar.gz/include/StAV/StAVImage.h Changed
43
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -46,6 +46,9 @@
9
     ST_CPPEXPORT static bool resize(const StImage& theImageFrom,
10
                                     StImage&       theImageTo);
11
 
12
+    ST_CPPEXPORT static bool resizePlane(const StImagePlane& theImageFrom,
13
+                                         StImagePlane&       theImageTo);
14
+
15
         public:
16
 
17
     /**
18
@@ -59,9 +62,14 @@
19
     ST_CPPEXPORT virtual ~StAVImage();
20
 
21
     /**
22
+     * Create new instance.
23
+     */
24
+    virtual StHandle<StImageFile> createEmpty() const ST_ATTR_OVERRIDE { return new StAVImage(); }
25
+
26
+    /**
27
      * Close currently opened image context and release memory.
28
      */
29
-    ST_CPPEXPORT virtual void close();
30
+    ST_CPPEXPORT virtual void close() ST_ATTR_OVERRIDE;
31
 
32
     /**
33
      * Decode image from specified file or memory pointer.
34
@@ -77,7 +85,7 @@
35
      */
36
     ST_CPPEXPORT virtual bool save(const StString& theFilePath,
37
                                    ImageType       theImageType,
38
-                                   StFormat        theSrcFormat = StFormat_AUTO);
39
+                                   StFormat        theSrcFormat = StFormat_AUTO) ST_ATTR_OVERRIDE;
40
 
41
         private:
42
 
43
sview-17_04.tar.gz/include/StAV/StAVPacket.h -> sview-20_08.tar.gz/include/StAV/StAVPacket.h Changed
9
 
1
@@ -25,6 +25,7 @@
2
         DATA_PACKET,
3
         FLUSH_PACKET,
4
         START_PACKET,
5
+        LAST_PACKET,
6
         END_PACKET,
7
         QUIT_PACKET,
8
     };
9
sview-17_04.tar.gz/include/StAV/stAV.h -> sview-20_08.tar.gz/include/StAV/stAV.h Changed
140
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -41,6 +41,25 @@
9
     #include <libavutil/spherical.h>
10
 #endif
11
 
12
+#if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100))
13
+    #define ST_AV_NEWCODECPAR
14
+#endif
15
+
16
+#ifndef AV_NUM_DATA_POINTERS
17
+    #define AV_NUM_DATA_POINTERS 4
18
+#endif
19
+
20
+// Compatibility with older FFmpeg (API change since 2015-07-27 - lavc 56.56.100 / 56.35.0)
21
+#ifndef AV_INPUT_BUFFER_PADDING_SIZE
22
+    #define AV_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE
23
+#endif
24
+#ifndef AV_CODEC_FLAG_GLOBAL_HEADER
25
+    #define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER
26
+#endif
27
+#ifndef AV_CODEC_FLAG2_IGNORE_CROP
28
+    #define AV_CODEC_FLAG2_IGNORE_CROP CODEC_FLAG2_IGNORE_CROP
29
+#endif
30
+
31
 #ifdef _MSC_VER
32
     #pragma warning(default : 4244)
33
 #endif
34
@@ -210,8 +229,11 @@
35
         ST_SHARED_CPPEXPORT AVPixelFormat GRAY16;    //!< Y, 16bpp
36
         // planar YUV formats
37
         ST_SHARED_CPPEXPORT AVPixelFormat YUV420P;   //!< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
38
+        ST_SHARED_CPPEXPORT AVPixelFormat YUVA420P;  //!< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
39
         ST_SHARED_CPPEXPORT AVPixelFormat YUV422P;   //!< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
40
+        ST_SHARED_CPPEXPORT AVPixelFormat YUVA422P;  //!< planar YUV 4:2:2  24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
41
         ST_SHARED_CPPEXPORT AVPixelFormat YUV444P;   //!< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
42
+        ST_SHARED_CPPEXPORT AVPixelFormat YUVA444P;  //!< planar YUV 4:4:4  32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
43
         ST_SHARED_CPPEXPORT AVPixelFormat YUV410P;   //!< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
44
         ST_SHARED_CPPEXPORT AVPixelFormat YUV411P;   //!< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
45
         ST_SHARED_CPPEXPORT AVPixelFormat YUV440P;   //!< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
46
@@ -244,8 +266,12 @@
47
         // XYZ formats
48
         ST_SHARED_CPPEXPORT AVPixelFormat XYZ12;
49
         // HWAccel formats
50
-        ST_SHARED_CPPEXPORT AVPixelFormat DXVA2_VLD;
51
+        ST_SHARED_CPPEXPORT AVPixelFormat DXVA2_VLD; // Windows
52
+        ST_SHARED_CPPEXPORT AVPixelFormat VIDEOTOOLBOX_VLD; // macOS
53
 
54
+        /**
55
+         * @sa StImage::formatImgPixelFormat()
56
+         */
57
         ST_CPPEXPORT StCString getString(const AVPixelFormat theFrmt);
58
     }
59
 
60
@@ -261,6 +287,7 @@
61
         int  heightV;
62
         int  bitsPerComp;
63
         bool isFullScale;
64
+        bool hasAlpha;
65
     };
66
 
67
     /**
68
@@ -315,6 +342,39 @@
69
     }
70
 
71
     /**
72
+     * Return codec context from the stream using deprecated API.
73
+     * The new API suggests using AVStream::codecpar, but this is confusing.
74
+     * So we would better waiting until old API is completely removed.
75
+     */
76
+    inline AVCodecContext* getCodecCtx(const AVStream* theStream) {
77
+    ST_DISABLE_DEPRECATION_WARNINGS
78
+        return theStream->codec;
79
+    ST_ENABLE_DEPRECATION_WARNINGS
80
+    }
81
+
82
+    /**
83
+     * Get codec type from the stream.
84
+     */
85
+    inline AVMediaType getCodecType(const AVStream* theStream) {
86
+    #ifdef ST_AV_NEWCODECPAR
87
+        return theStream->codecpar->codec_type;
88
+    #else
89
+        return theStream->codec->codec_type;
90
+    #endif
91
+    }
92
+
93
+    /**
94
+     * Get codec id from the stream.
95
+     */
96
+    inline AVCodecID getCodecId(const AVStream* theStream) {
97
+    #ifdef ST_AV_NEWCODECPAR
98
+        return theStream->codecpar->codec_id;
99
+    #else
100
+        return theStream->codec->codec_id;
101
+    #endif
102
+    }
103
+
104
+    /**
105
      * av_version_info() wrapper; return FFmpeg version info.
106
      */
107
     ST_CPPEXPORT StString getVersionInfo();
108
@@ -330,6 +390,11 @@
109
     ST_CPPEXPORT bool setJavaVM(void* theJavaVM);
110
 
111
     /**
112
+     * avio_enum_protocols() wrapper for checking input protocol.
113
+     */
114
+    ST_CPPEXPORT bool isEnabledInputProtocol(const StString& theProtocol);
115
+
116
+    /**
117
      * Audio functions
118
      */
119
     namespace audio {
120
@@ -440,6 +505,19 @@
121
             return readTag(getFrameMetadata(theFrame), theKey, theValue);
122
         }
123
 
124
+        /**
125
+         * Retrieve language id from the stream.
126
+         */
127
+        inline StString readLang(AVStream* theStream) {
128
+        #if(LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 5, 0))
129
+            StString aLang;
130
+            stAV::meta::readTag(theStream, stCString("language"), aLang);
131
+            return aLang;
132
+        #else
133
+            return theStream->language;
134
+        #endif
135
+        }
136
+
137
     }
138
 
139
 #ifdef ST_AV_NEWSTEREO
140
sview-17_04.tar.gz/include/StCore/StAndroidGlue.h -> sview-20_08.tar.gz/include/StCore/StAndroidGlue.h Changed
143
 
1
@@ -12,6 +12,8 @@
2
 #ifndef __StAndroidGlue_h_
3
 #define __StAndroidGlue_h_
4
 
5
+#include "StVirtualKeys.h"
6
+
7
 #include <StSlots/StSignal.h>
8
 #include <StStrings/StString.h>
9
 #include <StThreads/StMutex.h>
10
@@ -23,6 +25,7 @@
11
 
12
 class StAndroidGlue;
13
 class StApplication;
14
+class StKeysState;
15
 
16
 /**
17
  * Data associated with an ALooper fd that will be returned as the "outData" when that source has data ready.
18
@@ -38,50 +41,6 @@
19
 };
20
 
21
 /**
22
- * The sentry class for attaching the current thread to JavaVM.
23
- */
24
-class StJNIEnv {
25
-
26
-        public:
27
-
28
-    /**
29
-     * Main constructor, tries to attach JavaVM to the current thread.
30
-     */
31
-    ST_CPPEXPORT StJNIEnv(JavaVM* theJavaVM);
32
-
33
-    /**
34
-     * Destructor, automatically detaches JavaVM from current thread.
35
-     * Has no effect if JavaVM has been attached to the thread before creating this sentry.
36
-     */
37
-    ST_CPPEXPORT ~StJNIEnv();
38
-
39
-    /**
40
-     * Detach from current thread right now.
41
-     * Has no effect if JavaVM has been attached to the thread before creating this sentry.
42
-     */
43
-    ST_CPPEXPORT void detach();
44
-
45
-    /**
46
-     * Cast to actual JNIEnv instance.
47
-     */
48
-    ST_LOCAL JNIEnv* operator->() const {
49
-        return myJniEnv;
50
-    }
51
-
52
-    /**
53
-     * Return true if JNI environment is NULL.
54
-     */
55
-    ST_LOCAL bool isNull() const { return myJniEnv == NULL; }
56
-
57
-        private:
58
-
59
-    JavaVM* myJavaVM;   //!< pointer to global Java VM instance
60
-    JNIEnv* myJniEnv;   //!< JNI environment for working thread
61
-    bool    myToDetach; //!< flag to detach
62
-
63
-};
64
-
65
-/**
66
  * Interface for the standard glue code of a threaded application.
67
  */
68
 class StAndroidGlue {
69
@@ -201,6 +160,16 @@
70
     ST_CPPEXPORT void setWindowFlags(const int theFlags);
71
 
72
     /**
73
+     * Setup window title.
74
+     */
75
+    ST_CPPEXPORT void setWindowTitle(const StString& theTitle);
76
+
77
+    /**
78
+     * Set/release WAKE_LOCK.
79
+     */
80
+    ST_CPPEXPORT void setWakeLock(const StString& theTitle, bool theToLock);
81
+
82
+    /**
83
      * Turn stereo output on using device-specific API.
84
      */
85
     ST_CPPEXPORT void setHardwareStereoOn(const bool theToEnable);
86
@@ -232,10 +201,12 @@
87
      * @param theNewFile pop onNewIntent() open file event
88
      * @param theQuaternion device orientation
89
      * @param theToSwapEyes swap left/right views
90
+     * @param theKeys       keys state
91
      */
92
     ST_CPPEXPORT void fetchState(StString&             theNewFile,
93
                                  StQuaternion<double>& theQuaternion,
94
-                                 bool&                 theToSwapEyes);
95
+                                 bool&                 theToSwapEyes,
96
+                                 const StKeysState&    theKeys);
97
 
98
     /**
99
      * Return device memory class.
100
@@ -294,7 +265,7 @@
101
      * Read the open file from currently set intent.
102
      * The method calls the Java method readOpenPath() of StActivity which will call setOpenPath().
103
      */
104
-    ST_CPPEXPORT void readOpenPath();
105
+    ST_CPPEXPORT void readOpenPath(bool theToNullifyIntent);
106
 
107
     ST_CPPEXPORT void printConfig();
108
     ST_CPPEXPORT void freeSavedState();
109
@@ -363,6 +334,11 @@
110
      */
111
     ST_LOCAL void setSwapEyes(bool theToSwapLR);
112
 
113
+    /**
114
+     * Return TRUE if key is processed by application.
115
+     */
116
+    ST_LOCAL bool isKeyOverridden(int theKeyCode);
117
+
118
         private: //! @name ANativeActivity callbacks
119
 
120
     ST_LOCAL static void processInputWrapper(StAndroidGlue*       theApp,
121
@@ -453,7 +429,10 @@
122
     AInputQueue*            myInputQueuePending;
123
     ANativeWindow*          myWindow;            //!< native window to draw into
124
     ANativeWindow*          myWindowPending;
125
+    StString                myWindowTitle;       //!< window title
126
+    StString                myWakeLockTitle;     //!< wake lock title
127
     bool                    myIsChangingSurface; //!< flag indicating surface changing state
128
+    bool                    myIsWakeLockSet;     //!< flag indicating WAKE_LOCK enabled state
129
     int                     myWindowFlags;       //!< active window flags
130
     int                     myActivityState;     //!< Current state of the app's activity (APP_CMD_START, APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP)
131
     int                     myMemoryClassMiB;    //!< device memory class
132
@@ -474,7 +453,10 @@
133
     StAndroidPollSource     myInputPollSource;
134
 
135
     StMutex                 myFetchLock;         //!< fetch data lock
136
+    bool                    myRegKeys[ST_VK_NB]; //!< map of registered (used in hot-key combinations) keys
137
     StString                myStAppClass;        //!< application class name (e.g. image, video)
138
+    StString                myBuildModel;        //!< android.os.Build.MODEL
139
+    StString                myBuildDevice;       //!< android.os.Build.DEVICE
140
     StString                myStereoApiId;       //!< stereo API identifier
141
     bool                    myToEnableStereoHW;  //!< on/off state of stereo API
142
     StString                myDndPath;           //!< intent data string
143
sview-17_04.tar.gz/include/StCore/StApplication.h -> sview-20_08.tar.gz/include/StCore/StApplication.h Changed
57
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StCore, window system independent C++ toolkit for writing OpenGL applications.
4
- * Copyright © 2009-2016 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -46,6 +46,27 @@
10
      */
11
     ST_CPPEXPORT static StHandle<StOpenInfo> parseProcessArguments();
12
 
13
+    /**
14
+     * Read default drawer from setting.
15
+     */
16
+    ST_CPPEXPORT static bool readDefaultDrawer(StHandle<StOpenInfo>& theInfo);
17
+
18
+    /**
19
+     * @return TRUE if specified drawer is set as default in settings.
20
+     */
21
+    ST_CPPEXPORT bool isDefaultDrawer(const StString& theDrawer) const;
22
+
23
+    /**
24
+     * Save the drawer as default in settings.
25
+     */
26
+    ST_CPPEXPORT void setDefaultDrawer(const StString& theDrawer) const;
27
+
28
+    /**
29
+     * Create a named parameter for setting drawer as default.
30
+     */
31
+    ST_CPPEXPORT StHandle<StBoolParamNamed> createDefaultDrawerParam(const StString& theDrawer,
32
+                                                                     const StString& theTitle) const;
33
+
34
         public:
35
 
36
     /**
37
@@ -106,6 +127,11 @@
38
     ST_CPPEXPORT int exec();
39
 
40
     /**
41
+     * @return file to open in another drawer
42
+     */
43
+    const StHandle<StOpenInfo>& getOpenFileInOtherDrawer() const { return myOpenFileOtherApp; }
44
+
45
+    /**
46
      * Return active renderer and main application window.
47
      */
48
     ST_CPPEXPORT const StHandle<StWindow>& getMainWindow() const;
49
@@ -318,6 +344,7 @@
50
     StHandle<StWindow>    myWindow;                //!< active renderer and main application window
51
     StHandle<StWindow>    mySwitchTo;              //!< new renderer to switch to
52
     StHandle<StOpenInfo>  myOpenFileInfo;          //!< file to open
53
+    StHandle<StOpenInfo>  myOpenFileOtherApp;      //!< file to open in another drawer
54
     std::map< int, StHandle<StAction> >
55
                           myActions;               //!< ID -> Action map
56
     std::map< std::string, int >
57
sview-17_04.tar.gz/include/StCore/StEvent.h -> sview-20_08.tar.gz/include/StCore/StEvent.h Changed
75
 
1
@@ -71,6 +71,7 @@
2
     stEvent_TouchMove,  //!< StTouchEvent,  touch moved
3
     stEvent_TouchCancel,//!< StTouchEvent,  touch cancelled
4
     stEvent_GestureCancel,     //!< StGestureEvent, abort the gestures
5
+    stEvent_Gesture1Tap,       //!< StGestureEvent, 1 finger  single tap
6
     stEvent_Gesture1DoubleTap, //!< StGestureEvent, 1 finger  double tap
7
     stEvent_Gesture2Move,      //!< StGestureEvent, 2 fingers moving in sync
8
     stEvent_Gesture2Rotate,    //!< StGestureEvent, 2 fingers rotating
9
@@ -186,6 +187,65 @@
10
     float         DeltaY;           //!< precise  delta for vertical   scroll
11
     bool          IsFromMultiTouch; //!< when true, scrolling is simulated from multi-touch gesture by system (OS X) and touches will come in parallel
12
 
13
+    /**
14
+     * Reset event.
15
+     */
16
+    void reset() {
17
+        Type  = stEvent_Scroll;
18
+        Time  = 0.0;
19
+        PointX = 0.0;
20
+        PointY = 0.0;
21
+        StepsX = 0;
22
+        StepsY = 0;
23
+        DeltaX = 0.0f;
24
+        DeltaY = 0.0f;
25
+        IsFromMultiTouch = false;
26
+    }
27
+
28
+    /**
29
+     * Initialize event.
30
+     */
31
+    void init(double theTime,
32
+              double thePointX,
33
+              double thePointY,
34
+              float  theDeltaX,
35
+              float  theDeltaY,
36
+              bool   theIsFromMultiTouch) {
37
+        Type  = stEvent_Scroll;
38
+        Time  = theTime;
39
+        PointX = thePointX;
40
+        PointY = thePointY;
41
+        StepsX = 0;
42
+        StepsY = 0;
43
+        DeltaX = theDeltaX;
44
+        DeltaY = theDeltaY;
45
+        IsFromMultiTouch = theIsFromMultiTouch;
46
+    }
47
+
48
+    /**
49
+     * Compute accumulated integer steps from X scroll event.
50
+     */
51
+    int accumulateStepsX(int theInc, int theStepSize) { return accumulateSteps(StepsX, theInc, theStepSize); }
52
+
53
+    /**
54
+     * Compute accumulated integer steps from Y scroll event.
55
+     */
56
+    int accumulateStepsY(int theInc, int theStepSize) { return accumulateSteps(StepsY, theInc, theStepSize); }
57
+
58
+    /**
59
+     * Compute accumulated integer steps from scroll event.
60
+     */
61
+    static int accumulateSteps(int& theAcc, int theInc, int theStepSize) {
62
+        theAcc += theInc;
63
+        int aNbSteps = 0;
64
+        for(; theAcc <= -theStepSize; theAcc += theStepSize) {
65
+            --aNbSteps;
66
+        }
67
+        for(; theAcc >= theStepSize; theAcc -= theStepSize) {
68
+            ++aNbSteps;
69
+        }
70
+        return aNbSteps;
71
+    }
72
 };
73
 
74
 /**
75
sview-17_04.tar.gz/include/StCore/StKeysState.h -> sview-20_08.tar.gz/include/StCore/StKeysState.h Changed
50
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StCore, window system independent C++ toolkit for writing OpenGL applications.
4
- * Copyright © 2013 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -32,6 +32,26 @@
10
     ST_CPPEXPORT ~StKeysState();
11
 
12
     /**
13
+     * Reset map of registered keys.
14
+     */
15
+    ST_CPPEXPORT void resetRegisteredKeys();
16
+
17
+    /**
18
+     * Return map of registered keys.
19
+     */
20
+    ST_LOCAL const bool* getRegisteredKeys() const { return myRegKeys; }
21
+
22
+    /**
23
+     * Register key.
24
+     */
25
+    ST_CPPEXPORT void registerKey(StVirtKey theKey);
26
+
27
+    /**
28
+     * Unregister key.
29
+     */
30
+    ST_CPPEXPORT void unregisterKey(StVirtKey theKey);
31
+
32
+    /**
33
      * Release all pressed keys (window lost input focus etc.).
34
      */
35
     ST_CPPEXPORT void reset();
36
@@ -83,9 +103,10 @@
37
 
38
         private:
39
 
40
-    mutable StMutex myLock; //!< mutex for thread-safe access
41
-    bool    myKeys[256];    //!< virtual keys pressed state
42
-    double  myTimes[256];   //!< time when key was pressed or released
43
+    mutable StMutex myLock;              //!< mutex for thread-safe access
44
+    double          myTimes  [ST_VK_NB]; //!< time when key was pressed or released
45
+    bool            myKeys   [ST_VK_NB]; //!< virtual keys pressed state
46
+    bool            myRegKeys[ST_VK_NB]; //!< registered keys (used by some hot-keys)
47
 
48
 };
49
 
50
sview-17_04.tar.gz/include/StCore/StMonitor.h -> sview-20_08.tar.gz/include/StCore/StMonitor.h Changed
47
 
1
@@ -118,30 +118,22 @@
2
     /**
3
      * @return current vertical refresh rate
4
      */
5
-    ST_LOCAL int getFreq() const {
6
-        return myFreq;
7
-    }
8
+    ST_LOCAL float getFreq() const { return myFreq; }
9
 
10
     /**
11
      * @param theFrequency current vertical refresh rate
12
      */
13
-    ST_LOCAL void setFreq(const int theFrequency) {
14
-        myFreq = theFrequency;
15
-    }
16
+    ST_LOCAL void setFreq(float theFrequency) { myFreq = theFrequency; }
17
 
18
     /**
19
      * @return maximal vertical refresh rate
20
      */
21
-    ST_LOCAL int getFreqMax() const {
22
-        return myFreqMax;
23
-    }
24
+    ST_LOCAL float getFreqMax() const { return myFreqMax; }
25
 
26
     /**
27
      * @param theFrequencyMax maximal vertical refresh rate
28
      */
29
-    ST_LOCAL void setFreqMax(const int theFrequencyMax) {
30
-        myFreqMax = theFrequencyMax;
31
-    }
32
+    ST_LOCAL void setFreqMax(float theFrequencyMax) { myFreqMax = theFrequencyMax; }
33
 
34
     /**
35
      * @return GPU to which monitor is connected to
36
@@ -227,8 +219,8 @@
37
     StEDIDParser myEdid;    //!< EDID data block if available
38
     StRectI_t    myRect;    //!< virtual space (rectangle)
39
     int          mySysId;   //!< monitor id
40
-    int          myFreq;    //!< frequency in Hertz
41
-    int          myFreqMax; //!< maximum frequency in Hertz
42
+    float        myFreq;    //!< frequency in Hertz
43
+    float        myFreqMax; //!< maximum frequency in Hertz
44
     float        myScale;   //!< hight pixel density scale factor
45
     Orientation  myOrient;  //!< monitor orientation
46
 
47
sview-17_04.tar.gz/include/StCore/StVirtualKeys.h -> sview-20_08.tar.gz/include/StCore/StVirtualKeys.h Changed
40
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StCore, window system independent C++ toolkit for writing OpenGL applications.
4
- * Copyright © 2007-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2007-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -299,7 +299,7 @@
10
     ST_VK_OEM_MINUS  = 0xBD,   // 189 = VK_OEM_MINUS   | '-' any country
11
     ST_VK_PERIOD     = 0xBE,   // 190 = VK_OEM_PERIOD  | '.' any country
12
     ST_VK_SLASH      = 0xBF,   // 191 = VK_OEM_2       | '/?' for US
13
-    ///ST_VK_OEM_3       = 0xC0,  // 192 = VK_OEM_3       | '`~' for US*
14
+    ST_VK_TILDE      = 0xC0,   // 192 = VK_OEM_3       | '`~' for US*
15
 
16
     ST_VK_BRACKETLEFT  = 0xDB, // 219 = VK_OEM_4       | '[{' for US
17
     ST_VK_BACKSLASH    = 0xDC, // 220 = VK_OEM_5       | '\|' for US
18
@@ -312,6 +312,21 @@
19
     ST_VK_FUNCTION     = 0xD9, // 217 | OS X fn key      (NSFunctionKeyMask)
20
 
21
 };
22
+enum {
23
+    ST_VK_NB = 256 //!< maximum number of virtual keys
24
+};
25
+
26
+/**
27
+ * Remove modifiers from hot key combination and return the base virtual key.
28
+ */
29
+ST_LOCAL inline StVirtKey getBaseKeyFromHotKey(unsigned int theHotKey) {
30
+    unsigned int aKey = theHotKey & ~(ST_VF_SHIFT | ST_VF_CONTROL | ST_VF_MENU | ST_VF_COMMAND | ST_VF_FUNCTION);
31
+    if(aKey == 0
32
+    || aKey >= ST_VK_NB) {
33
+        return ST_VK_NULL;
34
+    }
35
+    return (StVirtKey )aKey;
36
+}
37
 
38
 /**
39
  * Encode single Virtual Key.
40
sview-17_04.tar.gz/include/StCore/StWindow.h -> sview-20_08.tar.gz/include/StCore/StWindow.h Changed
70
 
1
@@ -96,6 +96,7 @@
2
     StWinAttr_SlaveMon,            //!< integer, slave window monitor id, 1 by default
3
     StWinAttr_SplitCfg,            //!< StWinSplit, split master window
4
     StWinAttr_ToAlignEven,         //!< boolean, align window position to even numbers, FALSE by default
5
+    StWinAttr_ExclusiveFullScreen, //!< boolean, exclusive fullscreen mode, FALSE by default
6
 };
7
 
8
 typedef struct tagStSlaveWindowCfg {
9
@@ -351,7 +352,7 @@
10
      * @param theWinEnum subwindow ID
11
      * @return rectangle within window from bottom-left corner (ready for OpenGL calls)
12
      */
13
-    ST_CPPEXPORT StGLBoxPx stglViewport(const int theWinEnum) const;
14
+    ST_CPPEXPORT virtual StGLBoxPx stglViewport(const int theWinEnum) const;
15
 
16
     /**
17
      * @return GUI scale factor for compatibility with low-resolution and high-resolution displays
18
@@ -420,6 +421,11 @@
19
     ST_CPPEXPORT void setStereoOutput(bool theStereoState);
20
 
21
     /**
22
+    * Return maximum display update framerate.
23
+    */
24
+    ST_CPPEXPORT virtual float getMaximumTargetFps() const;
25
+
26
+    /**
27
      * @return FPS control rule
28
      */
29
     ST_CPPEXPORT double getTargetFps() const;
30
@@ -478,6 +484,11 @@
31
     ST_CPPEXPORT virtual StQuaternion<double> getDeviceOrientation() const;
32
 
33
     /**
34
+     * Return custom stereo projection frustums.
35
+     */
36
+    ST_CPPEXPORT virtual bool getCustomProjection(StRectF_t& theLeft, StRectF_t& theRight) const;
37
+
38
+    /**
39
      * Return TRUE if Left/Right eyes should be swapped by external event.
40
      */
41
     ST_CPPEXPORT virtual bool toSwapEyesHW() const;
42
@@ -573,13 +584,6 @@
43
     ST_CPPEXPORT void stglSwap(const int theWinEnum);
44
 
45
     /**
46
-     * This method should be called only by inheritors
47
-     * to override keyboard input logic.
48
-     * @return cached keyboard keys state for this window
49
-     */
50
-    ST_CPPEXPORT StKeysState& changeKeysState();
51
-
52
-    /**
53
      * @return upload time in seconds
54
      */
55
     ST_CPPEXPORT double getEventTime(const uint32_t theTime) const;
56
@@ -608,6 +612,13 @@
57
 
58
         public:
59
 
60
+    /**
61
+     * This method should be called only by inheritors
62
+     * to override keyboard input logic.
63
+     * @return cached keyboard keys state for this window
64
+     */
65
+    ST_CPPEXPORT StKeysState& changeKeysState();
66
+
67
     ST_CPPEXPORT void* getNativeOglWin() const;
68
     ST_CPPEXPORT void* getNativeOglDC()  const;
69
     ST_CPPEXPORT void* getNativeOglRC()  const;
70
sview-17_04.tar.gz/include/StFT/StFTFont.h -> sview-20_08.tar.gz/include/StFT/StFTFont.h Changed
198
 
1
@@ -26,13 +26,21 @@
2
     StString Italic;
3
     StString BoldItalic;
4
 
5
-    ST_LOCAL StFTFontFamily() {}
6
+    // face index within font container
7
+    int RegularFace;
8
+    int BoldFace;
9
+    int ItalicFace;
10
+    int BoldItalicFace;
11
+
12
+    ST_LOCAL StFTFontFamily() : RegularFace (0), BoldFace (0), ItalicFace (0), BoldItalicFace (0) {}
13
 };
14
 
15
 struct StFTFontPack {
16
     StFTFontFamily Western;
17
     StFTFontFamily CJK;
18
     StFTFontFamily Korean;
19
+    StFTFontFamily Arabic;      //!< fallback font for Arabic letters
20
+    StFTFontFamily MiscSymbols; //!< fallback font for Miscellaneous Symbols
21
 };
22
 
23
 /**
24
@@ -70,8 +78,10 @@
25
      */
26
     enum Subset {
27
         Subset_General,
28
-        Subset_Korean,  //!< modern Korean letters
29
-        Subset_CJK,     //!< Chinese characters (Chinese, Japanese, Korean and Vietnam)
30
+        Subset_Korean,      //!< modern Korean letters
31
+        Subset_CJK,         //!< Chinese characters (Chinese, Japanese, Korean and Vietnam)
32
+        Subset_Arabic,      //!< Arabic  characters
33
+        Subset_MiscSymbols, //!< Miscellaneous Symbols 0x2600 - 0x26FF
34
         SubsetsNB
35
     };
36
 
37
@@ -83,7 +93,9 @@
38
             || (theUChar >= 0x04E00 && theUChar <= 0x09FFF)
39
             || (theUChar >= 0x0F900 && theUChar <= 0x0FAFF)
40
             || (theUChar >= 0x20000 && theUChar <= 0x2A6DF)
41
-            || (theUChar >= 0x2F800 && theUChar <= 0x2FA1F);
42
+            || (theUChar >= 0x2F800 && theUChar <= 0x2FA1F)
43
+            //
44
+            || (theUChar >= 0x030A0 && theUChar <= 0x030FF); // Katakana (Japanese) is NOT part of CJK, but CJK fonts usually include these symbols
45
     }
46
 
47
     /**
48
@@ -96,6 +108,27 @@
49
     }
50
 
51
     /**
52
+     * @return true if specified character is within subset of Miscellaneous Symbols
53
+     */
54
+    ST_LOCAL static bool isMiscSymbol(stUtf32_t theUChar) {
55
+        return (theUChar >= 0x02600 && theUChar <= 0x026FF);
56
+    }
57
+
58
+    /**
59
+    * @return true if specified character is within subset of Arabic characters
60
+    */
61
+    ST_LOCAL static bool isArabic(stUtf32_t theUChar) {
62
+      return (theUChar >= 0x00600 && theUChar <= 0x006FF);
63
+    }
64
+
65
+    /**
66
+     * @return true if specified character should be displayed in Right-to-Left order.
67
+     */
68
+    ST_LOCAL static bool isRightToLeft(stUtf32_t theUChar) {
69
+        return (theUChar >= 0x00600 && theUChar <= 0x006FF); // Arabic
70
+    }
71
+
72
+    /**
73
      * Determine Unicode subset for specified character
74
      */
75
     ST_LOCAL static Subset subset(const stUtf32_t theUChar) {
76
@@ -103,6 +136,10 @@
77
             return Subset_CJK;
78
         } else if(isKorean(theUChar)) {
79
             return Subset_Korean;
80
+        } else if(isArabic(theUChar)) {
81
+            return Subset_Arabic;
82
+        } else if(isMiscSymbol(theUChar)) {
83
+          return Subset_MiscSymbols;
84
         }
85
         return Subset_General;
86
     }
87
@@ -147,11 +184,15 @@
88
     /**
89
      * Load the font from specified path.
90
      * @param theFontPath path to the font
91
+     * @param theFaceId   face id within the file (0 by default)
92
      * @param theStyle    the font style
93
+     * @param theToSyntItalic synthesize italic style
94
      * @return true on success
95
      */
96
-    ST_CPPEXPORT bool load(const StString&       theFontPath,
97
-                           const StFTFont::Style theStyle);
98
+    ST_CPPEXPORT bool load(const StString& theFontPath,
99
+                           const int theFaceId,
100
+                           const StFTFont::Style theStyle,
101
+                           const bool theToSyntItalic = false);
102
 
103
     /**
104
      * Load the font from data array.
105
@@ -231,7 +272,7 @@
106
      * Assuming text rendered horizontally.
107
      */
108
     ST_CPPEXPORT void addAdvanceX(const stUtf32_t  theUCharNext,
109
-                                  StVec2<GLfloat>& thePen);
110
+                                  StVec2<GLfloat>& thePen) const;
111
 
112
     /**
113
      * Compute advance to the next character with kerning applied when applicable
114
@@ -248,7 +289,7 @@
115
      * Assuming text rendered vertically.
116
      */
117
     ST_CPPEXPORT void addAdvanceY(const stUtf32_t  theUCharNext,
118
-                                  StVec2<GLfloat>& thePen);
119
+                                  StVec2<GLfloat>& thePen) const;
120
 
121
     /**
122
      * Compute advance to the next character with kerning applied when applicable
123
@@ -263,7 +304,7 @@
124
      * Compute advance to the next character with kerning applied when applicable.
125
      * Assuming text rendered horizontally.
126
      */
127
-    ST_CPPEXPORT float getAdvanceX(const stUtf32_t theUCharNext);
128
+    ST_CPPEXPORT float getAdvanceX(const stUtf32_t theUCharNext) const;
129
 
130
     /**
131
      * Compute advance to the next character with kerning applied when applicable.
132
@@ -276,7 +317,7 @@
133
      * Compute advance to the next character with kerning applied when applicable.
134
      * Assuming text rendered vertically.
135
      */
136
-    ST_CPPEXPORT float getAdvanceY(const stUtf32_t theUCharNext);
137
+    ST_CPPEXPORT float getAdvanceY(const stUtf32_t theUCharNext) const;
138
 
139
     /**
140
      * Compute advance to the next character with kerning applied when applicable.
141
@@ -307,6 +348,13 @@
142
     }
143
 
144
     /**
145
+     * @return font face index
146
+     */
147
+    ST_LOCAL int getFaceIndex(const StFTFont::Style theStyle) const {
148
+        return myFontFaces[theStyle];
149
+    }
150
+
151
+    /**
152
      * @return active font style
153
      */
154
     ST_LOCAL StFTFont::Style getActiveStyle() const {
155
@@ -332,6 +380,13 @@
156
         return mySubsets[Subset_Korean];
157
     }
158
 
159
+    /**
160
+     * @return true if this font contains glyphs of specified subset
161
+     */
162
+    ST_LOCAL bool hasSubset(Subset theSubset) const {
163
+        return mySubsets[theSubset];
164
+    }
165
+
166
         protected:
167
 
168
     /**
169
@@ -339,6 +394,13 @@
170
      */
171
     ST_CPPEXPORT bool loadGlyph(const stUtf32_t theUChar);
172
 
173
+    /**
174
+     * Wrapper for FT_Get_Kerning - retrieve kerning values.
175
+     */
176
+    ST_CPPEXPORT bool getKerning(FT_Vector&      theKern,
177
+                                 const stUtf32_t theUCharCurr,
178
+                                 const stUtf32_t theUCharNext) const;
179
+
180
         private:
181
 
182
     /**
183
@@ -354,13 +416,13 @@
184
     StFTFont::Style       myStyle;               //!< active FT face style
185
     FT_Face               myFTFaces[StylesNB];   //!< FT face objects
186
     StString              myFontPaths[StylesNB]; //!< font paths
187
+    int                   myFontFaces[StylesNB]; //!< font face ids
188
     bool                  mySubsets[SubsetsNB];
189
     FT_Int32              myLoadFlags;           //!< default load flags
190
     unsigned int          myGlyphMaxWidth;       //!< maximum glyph width
191
     unsigned int          myGlyphMaxHeight;      //!< maximum glyph height
192
 
193
     StImagePlane          myGlyphImg;            //!< cached glyph plane
194
-    FT_Vector             myKernAdvance;         //!< buffer variable
195
     stUtf32_t             myUChar;               //!< currently loaded unicode character
196
 
197
 };
198
sview-17_04.tar.gz/include/StFT/StFTFontRegistry.h -> sview-20_08.tar.gz/include/StFT/StFTFontRegistry.h Changed
13
 
1
@@ -64,6 +64,11 @@
2
     void searchFiles(const StArrayList<StString>& theNames,
3
                      const bool                   theIsMajor);
4
 
5
+    /**
6
+     * Process font file.
7
+     */
8
+    bool registerFamily(const StString& theFontPath, int theFaceId);
9
+
10
         private:
11
 
12
     StArrayList<StString> myExtensions;  //!< list of supported font file extensions
13
sview-17_04.tar.gz/include/StFile/StFileNode.h -> sview-20_08.tar.gz/include/StFile/StFileNode.h Changed
76
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -10,10 +10,21 @@
9
 #define __StFileNode_H__
10
 
11
 #include <StFile/StNode.h>
12
-#include <StFile/StMIME.h>
13
+#include <StFile/StMIMEList.h>
14
 #include <StTemplates/StHandle.h>
15
 
16
-class StMIMEList;
17
+/**
18
+ * Structure defining Open File dialog content.
19
+ */
20
+struct StOpenFileName {
21
+    StString   Folder;            //!< folder to open
22
+    StString   Title;             //!< dialog title
23
+    StMIMEList Filter;            //!< main file filter
24
+    StString   FilterTitle;       //!< main file filter title; "All supported" will be displayed when empty
25
+    StMIMEList ExtraFilter;       //!< extra file filter (optional)
26
+    StString   ExtraFilterTitle;  //!< extra file filter title
27
+};
28
+
29
 class StFileNode : public StNode {
30
 
31
         private:
32
@@ -205,6 +216,18 @@
33
     ST_CPPEXPORT static bool isFileExists(const StCString& thePath);
34
 
35
     /**
36
+     * @param thePath file path
37
+     * @return true if file/folder has read-only flag
38
+     */
39
+    ST_CPPEXPORT static bool isFileReadOnly(const StCString& thePath);
40
+
41
+    /**
42
+     * @param thePath file path
43
+     * @return true if file attributes have been successfully modified
44
+     */
45
+    ST_CPPEXPORT static bool removeReadOnlyFlag(const StCString& thePath);
46
+
47
+    /**
48
      * Tries to remove file from filesystem.
49
      * @return true on success.
50
      */
51
@@ -263,18 +286,14 @@
52
 
53
     /**
54
      * Open native system open file dialog.
55
-     * @param theFolder      path to open
56
-     * @param theTitle       dialog title
57
-     * @param theFilter      files filter
58
-     * @param theOutFilePath file selected by user
59
-     * @param toSave         flag this dialog to open or save file
60
+     * @param theFilePath [in] [out] file selected by user
61
+     * @param theInfo [in] file open dialog definition
62
+     * @param theToSave [in] flag this dialog to open or save file
63
      * @return
64
      */
65
-    ST_CPPEXPORT static bool openFileDialog(const StString&   theFolder,
66
-                                            const StString&   theTitle,
67
-                                            const StMIMEList& theFilter,
68
-                                            StString&         theOutFilePath,
69
-                                            bool              toSave);
70
+    ST_CPPEXPORT static bool openFileDialog(StString& theFilePath,
71
+                                            const StOpenFileName& theInfo,
72
+                                            bool theToSave);
73
 
74
     /**
75
      * Function used where not possible use native Unicode paths.
76
sview-17_04.tar.gz/include/StFile/StFolder.h -> sview-20_08.tar.gz/include/StFile/StFolder.h Changed
8
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
sview-17_04.tar.gz/include/StFile/StMIMEList.h -> sview-20_08.tar.gz/include/StFile/StMIMEList.h Changed
21
 
1
@@ -54,6 +54,19 @@
2
     }
3
 
4
     /**
5
+     * Verify the filename extension is in supported list.
6
+     */
7
+    bool checkExtension(const StString& theExt) const {
8
+        for(size_t aMimeId = 0; aMimeId < StArrayList<StMIME>::size(); ++aMimeId) {
9
+            const StString& anExt = StArrayList<StMIME>::getValue(aMimeId).getExtension();
10
+            if(anExt.isEqualsIgnoreCase(theExt)) {
11
+                return true;
12
+            }
13
+        }
14
+        return false;
15
+    }
16
+
17
+    /**
18
      * Returns toString, splitter argument should not be changed!
19
      * @param theSplitter (const StString& ) - splitter char should not be changed!
20
      * @return string (StString ).
21
sview-17_04.tar.gz/include/StFile/StNode.h -> sview-20_08.tar.gz/include/StFile/StNode.h Changed
28
 
1
@@ -72,15 +72,18 @@
2
     }
3
 
4
     virtual StString getPath() const {
5
-        if(getParent() != NULL) {
6
-            StString parentPath = getParent()->getPath();
7
-            if(parentPath.isEmpty()) {
8
-                return subPath;
9
-            } else {
10
-                return parentPath + StString(SYS_FS_SPLITTER) + subPath;
11
-            }
12
+        if(getParent() == NULL) {
13
+            return subPath;
14
         }
15
-        return subPath;
16
+
17
+        const StString parentPath = getParent()->getPath();
18
+        if(parentPath.isEmpty()) {
19
+            return subPath;
20
+        }
21
+
22
+        return parentPath.isEndsWith(SYS_FS_SPLITTER)
23
+             ? parentPath + subPath
24
+             : parentPath + StString(SYS_FS_SPLITTER) + subPath;
25
     }
26
 
27
     bool operator==(const StNode& compare) const {
28
sview-17_04.tar.gz/include/StFile/StRawFile.h -> sview-20_08.tar.gz/include/StFile/StRawFile.h Changed
23
 
1
@@ -68,6 +68,13 @@
2
     ST_CPPEXPORT void initBuffer(size_t theDataSize);
3
 
4
     /**
5
+     * Wrap external buffer.
6
+     */
7
+    ST_CPPEXPORT void wrapBuffer(stUByte_t* theBuffer,
8
+                                 size_t theDataSize);
9
+
10
+
11
+    /**
12
      * Free current buffer.
13
      */
14
     ST_CPPEXPORT void freeBuffer();
15
@@ -159,6 +166,7 @@
16
     stUByte_t*   myBuffer;     //!< buffer with file content
17
     size_t       myBuffSize;   //!< buffer size
18
     size_t       myLength;     //!< data length
19
+    bool         myIsOwnData;  //!< flag indicating that myBuffer was allocated by this class
20
 
21
 };
22
 
23
sview-17_04.tar.gz/include/StGL/StGLContext.h -> sview-20_08.tar.gz/include/StGL/StGLContext.h Changed
87
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2012-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2012-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -159,13 +159,15 @@
9
     StGLArbFbo*     arbFbo;     //!< GL_ARB_framebuffer_object
10
     bool            arbNPTW;    //!< GL_ARB_texture_non_power_of_two
11
     bool            arbTexRG;   //!< GL_ARB_texture_rg
12
+    bool            arbTexFloat;//!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0)
13
     bool            arbTexClear;//!< GL_ARB_clear_texture
14
-    bool            hasUnpack;  //!< GL_PACK_ROW_LENGTH / GL_UNPACK_ROW_LENGTH can be used - OpenGL ES 3.0+ or any desktop
15
     bool            hasHighp;   //!< highp in GLSL ES fragment shader is supported
16
     bool            hasTexRGBA8;//!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8
17
     bool            extTexBGRA8;//!< GL_EXT_texture_format_BGRA8888 for OpenGL ES
18
+    bool            extTexR16;  //!< GL_EXT_texture_norm16 on OpenGL ES
19
     StGLFunctions*  extAll;     //!< access to ALL extensions for advanced users
20
     bool            extSwapTear;//!< WGL_EXT_swap_control_tear/GLX_EXT_swap_control_tear
21
+    bool            khrFlushControl; //!< GL_KHR_context_flush_control / WGL_ARB_context_flush_control / GLX_ARB_context_flush_control / EGL_KHR_context_flush_control
22
 
23
         public:    //! @name class interface
24
 
25
@@ -243,12 +245,7 @@
26
     /**
27
      * Return capabilities of currently active device.
28
      */
29
-    ST_LOCAL StGLDeviceCaps getDeviceCaps() const {
30
-        StGLDeviceCaps aCaps;
31
-        aCaps.maxTexDim = myMaxTexDim;
32
-        aCaps.hasUnpack = hasUnpack;
33
-        return aCaps;
34
-    }
35
+    ST_LOCAL const StGLDeviceCaps& getDeviceCaps() const { return myDevCaps; }
36
 
37
     ST_LOCAL GLint getVersionMajor() const {
38
         return myVerMajor;
39
@@ -266,7 +263,7 @@
40
      * @return value for GL_MAX_TEXTURE_SIZE.
41
      */
42
     ST_LOCAL GLint getMaxTextureSize() const {
43
-        return myMaxTexDim;
44
+        return myDevCaps.maxTexDim;
45
     }
46
 
47
     /**
48
@@ -410,6 +407,18 @@
49
                                                 int          theLength,
50
                                                 const char*  theMessage);
51
 
52
+        public:
53
+
54
+    /**
55
+     * Return auxiliary temporary image buffer.
56
+     */
57
+    ST_LOCAL StImagePlane& getTmpImagePlane1() { return myTmpPlane1; }
58
+
59
+    /**
60
+     * Return auxiliary temporary image buffer.
61
+     */
62
+    ST_LOCAL StImagePlane& getTmpImagePlane2() { return myTmpPlane2; }
63
+
64
         public: //! @name auxiliary methods
65
 
66
     /**
67
@@ -443,15 +452,18 @@
68
     StHandle<StResourceManager>
69
                             myResMgr;             //!< file resources manager
70
     StHandle<StMsgQueue>    myMsgQueue;           //!< messages queue
71
+    StGLDeviceCaps          myDevCaps;            //!< device caps
72
     GlVendor                myGlVendor;           //!< driver vendor
73
     GPU_Name                myGpuName;            //!< GPU name
74
     GLint                   myVerMajor;           //!< cached GL version major number
75
     GLint                   myVerMinor;           //!< cached GL version minor number
76
-    GLint                   myMaxTexDim;          //!< maximum texture dimension
77
     BufferBits              myWindowBits;         //!< default buffer (window) bits
78
     BufferBits              myFBOBits;            //!< FBO bits
79
     bool                    myWasInit;            //!< initialization state
80
 
81
+    StImagePlane            myTmpPlane1;          //!< auxiliary temporary image buffer
82
+    StImagePlane            myTmpPlane2;          //!< auxiliary temporary image buffer
83
+
84
         protected: //! @name current state
85
 
86
     std::stack<StGLBoxPx>   myScissorStack;       //!< cached stack of scissor rectangles
87
sview-17_04.tar.gz/include/StGL/StGLDeviceCaps.h -> sview-20_08.tar.gz/include/StGL/StGLDeviceCaps.h Changed
51
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2016-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -9,7 +9,7 @@
9
 #ifndef __StGLDeviceCaps_h_
10
 #define __StGLDeviceCaps_h_
11
 
12
-#include <stTypes.h>
13
+#include <StImage/StImagePlane.h>
14
 
15
 /**
16
  * Structure defining OpenGL device capabilities
17
@@ -23,13 +23,32 @@
18
 
19
     /**
20
      * Device support data transferring with row unpack size specified.
21
+     * GL_PACK_ROW_LENGTH / GL_UNPACK_ROW_LENGTH can be used - OpenGL ES 3.0+ or any desktop.
22
      */
23
     bool hasUnpack;
24
 
25
     /**
26
+     * Return TRUE if image format can be uploaded into OpenGL texture.
27
+     */
28
+    bool isSupportedFormat(StImagePlane::ImgFormat theFormat) const { return mySupportedFormats[theFormat]; }
29
+
30
+    /**
31
+     * Set if image format can be uploaded into OpenGL texture.
32
+     */
33
+    void setSupportedFormat(StImagePlane::ImgFormat theFormat, bool theIsSupported) { mySupportedFormats[theFormat] = theIsSupported; }
34
+
35
+    /**
36
      * Empty constructor.
37
      */
38
-    ST_LOCAL StGLDeviceCaps() : maxTexDim(0), hasUnpack(true) {}
39
+    ST_LOCAL StGLDeviceCaps()
40
+    : maxTexDim(0), hasUnpack(true) {
41
+        stMemZero(mySupportedFormats, sizeof(mySupportedFormats));
42
+    }
43
+
44
+        private:
45
+
46
+    bool mySupportedFormats[StImagePlane::ImgNB];
47
+
48
 };
49
 
50
 #endif // __StGLDeviceCaps_h_
51
sview-17_04.tar.gz/include/StGL/StGLFontEntry.h -> sview-20_08.tar.gz/include/StGL/StGLFontEntry.h Changed
16
 
1
@@ -145,6 +145,14 @@
2
     }
3
 
4
     /**
5
+     * @return true if this font contains glyphs of specified subset
6
+     */
7
+    ST_LOCAL bool hasSubset(StFTFont::Subset theSubset) const {
8
+        return !myFont.isNull()
9
+             && myFont->hasSubset(theSubset);
10
+    }
11
+
12
+    /**
13
      * Compute glyph rectangle at specified pen position (on baseline)
14
      * and render it to texture if not already.
15
      * @param theCtx         active context
16
sview-17_04.tar.gz/include/StGL/StGLFunctions.h -> sview-20_08.tar.gz/include/StGL/StGLFunctions.h Changed
37
 
1
@@ -39,6 +39,7 @@
2
 
3
 // include main OpenGL header provided with system
4
 #if defined(__APPLE__)
5
+    #define GL_SILENCE_DEPRECATION
6
     #include <OpenGL/gl.h>
7
 #elif defined(ST_HAVE_GLES2) || defined(__ANDROID__)
8
     #include <GLES2/gl2.h>
9
@@ -1462,6 +1463,12 @@
10
                                                          const int* theAttribs);
11
     wglCreateContextAttribsARB_t wglCreateContextAttribsARB;
12
 
13
+        // WGL_ARB_context_flush_control
14
+
15
+    #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB       0x2097
16
+    #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB  0x0000
17
+    #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
18
+
19
         // WGL_NV_DX_interop
20
 
21
     typedef BOOL   (WINAPI *wglDXSetResourceShareHandleNV_t)(void* theObjectD3d, HANDLE theShareHandle);
22
@@ -1534,6 +1541,14 @@
23
     typedef int         (*glXSwapIntervalSGI_t)(int theInterval);
24
     glXSwapIntervalSGI_t glXSwapIntervalSGI;
25
 
26
+        public: //! @name GLX_ARB_context_flush_control
27
+
28
+#ifndef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
29
+    #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB       0x2097
30
+    #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB  0x0000
31
+    #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
32
+#endif
33
+
34
         // GLX_MESA_query_renderer
35
 
36
 #ifndef GLX_RENDERER_VENDOR_ID_MESA
37
sview-17_04.tar.gz/include/StGL/StGLProgram.h -> sview-20_08.tar.gz/include/StGL/StGLProgram.h Changed
9
 
1
@@ -25,6 +25,7 @@
2
         TEXTURE_SAMPLE_0 = 0, // GL_TEXTURE0
3
         TEXTURE_SAMPLE_1 = 1, // GL_TEXTURE1
4
         TEXTURE_SAMPLE_2 = 2, // GL_TEXTURE2
5
+        TEXTURE_SAMPLE_3 = 3, // GL_TEXTURE3
6
     };
7
 
8
         public:
9
sview-17_04.tar.gz/include/StGL/StGLTextFormatter.h -> sview-20_08.tar.gz/include/StGL/StGLTextFormatter.h Changed
13
 
1
@@ -177,6 +177,11 @@
2
      */
3
     ST_CPPEXPORT void newLine(const size_t theLastRect);
4
 
5
+    /**
6
+     * Flip left to right order.
7
+     */
8
+    ST_CPPEXPORT void flipLeftRight(size_t theCharFrom, size_t theCharTo);
9
+
10
         protected: //! @name configuration
11
 
12
     StAlignX              myAlignX;        //!< horizontal alignment style
13
sview-17_04.tar.gz/include/StGL/StGLTexture.h -> sview-20_08.tar.gz/include/StGL/StGLTexture.h Changed
85
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -11,8 +11,8 @@
9
 
10
 #include <StGL/StGLResource.h>
11
 #include <StStrings/StString.h>
12
+#include <StImage/StImagePlane.h>
13
 
14
-class StImagePlane;
15
 class StGLContext;
16
 
17
 #define GL_TEXTURE0 0x84C0
18
@@ -32,9 +32,9 @@
19
      * Currently GL_ALPHA is returned for grayscale image data.
20
      * @return true if internal format was found.
21
      */
22
-    ST_CPPEXPORT static bool getInternalFormat(const StGLContext&  theCtx,
23
-                                               const StImagePlane& theData,
24
-                                               GLint&              theInternalFormat);
25
+    ST_CPPEXPORT static bool getInternalFormat(const StGLContext& theCtx,
26
+                                               const StImagePlane::ImgFormat theFormat,
27
+                                               GLint& theInternalFormat);
28
 
29
     /**
30
      * Return true for GL_ALPHA / GL_RED formats.
31
@@ -165,7 +165,17 @@
32
      * After this call current texture will be undefined.
33
      */
34
     ST_CPPEXPORT void setMinMagFilter(StGLContext& theCtx,
35
-                                      const GLenum theMinMagFilter);
36
+                                      const GLenum theMinFilter,
37
+                                      const GLenum theMagFilter);
38
+
39
+    /**
40
+     * Change Min and Mag filter.
41
+     * After this call current texture will be undefined.
42
+     */
43
+    ST_LOCAL void setMinMagFilter(StGLContext& theCtx,
44
+                                  const GLenum theMinMagFilter) {
45
+        setMinMagFilter(theCtx, theMinMagFilter, theMinMagFilter);
46
+    }
47
 
48
     ST_LOCAL bool fill(StGLContext&        theCtx,
49
                        const StImagePlane& theData) {
50
@@ -190,7 +200,22 @@
51
                                 const GLenum        theTarget,
52
                                 const GLsizei       theRowFrom,
53
                                 const GLsizei       theRowTo,
54
-                                const GLsizei       theBatchRows = 128);
55
+                                const GLsizei       theBatchRows);
56
+
57
+    /**
58
+     * Fill the texture with the image plane.
59
+     * @param theCtx       current context
60
+     * @param theData      the image plane to copy data from
61
+     * @param theTarget    texture target
62
+     * @param theRowFrom   fill data from row (for both - input image plane and the texture!)
63
+     * @param theRowTo     fill data up to the row (0 means all rows)
64
+     * @return true on success
65
+     */
66
+    ST_CPPEXPORT bool fillPatch(StGLContext&        theCtx,
67
+                                const StImagePlane& theData,
68
+                                const GLenum        theTarget,
69
+                                const GLsizei       theRowFrom,
70
+                                const GLsizei       theRowTo);
71
 
72
     /**
73
      * @return GL texture ID.
74
@@ -222,7 +247,9 @@
75
     GLint   myTextFormat;  //!< texture format - GL_RGB, GL_RGBA,...
76
     GLuint  myTextureId;   //!< GL texture ID
77
     GLenum  myTextureUnit; //!< texture unit
78
-    GLenum  myTextureFilt; //!< current texture filter
79
+    GLenum  myFilterMin;   //!< current minify  texture filter (GL_TEXTURE_MIN_FILTER)
80
+    GLenum  myFilterMag;   //!< current magnify texture filter (GL_TEXTURE_MAG_FILTER)
81
+    int     myHasMipMaps;  //!< indicates if mip levels have been generated
82
 
83
         private:
84
 
85
sview-17_04.tar.gz/include/StGL/StParams.h -> sview-20_08.tar.gz/include/StGL/StParams.h Changed
135
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -18,10 +18,13 @@
9
  * Surface to map image onto.
10
  */
11
 enum StViewSurface {
12
-    StViewSurface_Plain,   //!< normal 2D image
13
-    StViewSurface_Cubemap, //!< cubemap texture
14
-    StViewSurface_Sphere,  //!< spherical panorama
15
-    //StViewSurface_Cylinder, //!< cylindrical panorama
16
+    StViewSurface_Plain,      //!< normal 2D image
17
+    StViewSurface_Theater,    //!< theater panorama
18
+    StViewSurface_Cubemap,    //!< cubemap texture
19
+    StViewSurface_Sphere,     //!< spherical panorama, 360 degrees
20
+    StViewSurface_Hemisphere, //!< spherical panorama, 180 degrees
21
+    StViewSurface_Cylinder,   //!< cylindrical panorama
22
+    StViewSurface_CubemapEAC, //!< equi-angular cubemap
23
 };
24
 
25
 /**
26
@@ -33,9 +36,13 @@
27
 
28
     static StString GET_VIEW_MODE_NAME(StViewSurface theViewMode) {
29
         switch(theViewMode) {
30
-            case StViewSurface_Cubemap: return "cubemap";
31
-            case StViewSurface_Sphere:  return "sphere";
32
-            case StViewSurface_Plain:   return "flat";
33
+            case StViewSurface_Cubemap:    return "cubemap";
34
+            case StViewSurface_CubemapEAC: return "eac";
35
+            case StViewSurface_Sphere:     return "sphere";
36
+            case StViewSurface_Hemisphere: return "hemisphere";
37
+            case StViewSurface_Cylinder:   return "cylinder";
38
+            case StViewSurface_Theater:    return "theater";
39
+            case StViewSurface_Plain:      return "flat";
40
         }
41
         return "flat";
42
     }
43
@@ -43,13 +50,43 @@
44
     static StViewSurface GET_VIEW_MODE_FROM_STRING(const StString& theViewModeStr) {
45
         if(theViewModeStr.isStartsWithIgnoreCase(stCString("cubemap"))) {
46
             return StViewSurface_Cubemap;
47
+        } else if(theViewModeStr.isStartsWithIgnoreCase(stCString("eac"))) {
48
+            return StViewSurface_CubemapEAC;
49
         } else if(theViewModeStr.isStartsWithIgnoreCase(stCString("sphere"))) {
50
             return StViewSurface_Sphere;
51
+        } else if(theViewModeStr.isStartsWithIgnoreCase(stCString("hemisphere"))) {
52
+            return StViewSurface_Hemisphere;
53
+        } else if(theViewModeStr.isStartsWithIgnoreCase(stCString("cylinder"))) {
54
+            return StViewSurface_Cylinder;
55
+        } else if(theViewModeStr.isStartsWithIgnoreCase(stCString("theater"))) {
56
+            return StViewSurface_Theater;
57
         } else {
58
             return StViewSurface_Plain;
59
         }
60
     }
61
 
62
+    /**
63
+     * Convert panorama mode into surface view.
64
+     */
65
+    static StViewSurface getViewSurfaceForPanoramaSource(StPanorama thePano, bool theToFallbackSphere) {
66
+        switch(thePano) {
67
+            case StPanorama_Cubemap6_1:
68
+            case StPanorama_Cubemap1_6:
69
+            case StPanorama_Cubemap3_2:
70
+                return StViewSurface_Cubemap;
71
+            case StPanorama_Cubemap3_2ytb:
72
+            case StPanorama_Cubemap2_3ytb:
73
+              return StViewSurface_CubemapEAC;
74
+            case StPanorama_Sphere:
75
+                return StViewSurface_Sphere;
76
+            case StPanorama_Hemisphere:
77
+                return StViewSurface_Hemisphere;
78
+            case StPanorama_OFF:
79
+                break;
80
+        }
81
+        return theToFallbackSphere ? StViewSurface_Sphere : StViewSurface_Plain;
82
+    }
83
+
84
         public:
85
 
86
     /**
87
@@ -272,7 +309,11 @@
88
     void moveToRight(const float theDuration = 0.02f) {
89
         switch(ViewingMode) {
90
             case StViewSurface_Sphere:
91
+            case StViewSurface_Hemisphere:
92
+            case StViewSurface_Cylinder:
93
+            case StViewSurface_Theater:
94
             case StViewSurface_Cubemap:
95
+            case StViewSurface_CubemapEAC:
96
                 myPanYaw += 100.0f * theDuration;
97
                 break;
98
             case StViewSurface_Plain:
99
@@ -284,7 +325,11 @@
100
     void moveToLeft(const float theDuration = 0.02f) {
101
         switch(ViewingMode) {
102
             case StViewSurface_Sphere:
103
+            case StViewSurface_Hemisphere:
104
+            case StViewSurface_Cylinder:
105
+            case StViewSurface_Theater:
106
             case StViewSurface_Cubemap:
107
+            case StViewSurface_CubemapEAC:
108
                 myPanYaw -= 100.0f * theDuration;
109
                 break;
110
             case StViewSurface_Plain:
111
@@ -308,7 +353,11 @@
112
     void moveToDown(const float theDuration = 0.02f) {
113
         switch(ViewingMode) {
114
             case StViewSurface_Sphere:
115
+            case StViewSurface_Hemisphere:
116
+            case StViewSurface_Cylinder:
117
+            case StViewSurface_Theater:
118
             case StViewSurface_Cubemap:
119
+            case StViewSurface_CubemapEAC:
120
                 myPanPitch = clipPitch(myPanPitch - 100.0f * theDuration);
121
                 break;
122
             case StViewSurface_Plain:
123
@@ -320,7 +369,11 @@
124
     void moveToUp(const float theDuration = 0.02f) {
125
         switch(ViewingMode) {
126
             case StViewSurface_Sphere:
127
+            case StViewSurface_Hemisphere:
128
+            case StViewSurface_Cylinder:
129
+            case StViewSurface_Theater:
130
             case StViewSurface_Cubemap:
131
+            case StViewSurface_CubemapEAC:
132
                 myPanPitch = clipPitch(myPanPitch + 100.0f * theDuration);
133
                 break;
134
             case StViewSurface_Plain:
135
sview-17_04.tar.gz/include/StGLMesh/StGLMesh.h -> sview-20_08.tar.gz/include/StGLMesh/StGLMesh.h Changed
10
 
1
@@ -197,6 +197,8 @@
2
         return myNormals;
3
     }
4
 
5
+    ST_LOCAL StArrayList<StGLVec4>& changeColors() { return myColors; }
6
+
7
     inline StArrayList<GLuint>& changeIndices() {
8
         return myIndices;
9
     }
10
sview-20_08.tar.gz/include/StGLMesh/StGLUVCylinder.h Added
71
 
1
@@ -0,0 +1,69 @@
2
+/**
3
+ * Copyright © 2019-2020 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#ifndef __StGLUVCylinder_h_
11
+#define __StGLUVCylinder_h_
12
+
13
+#include "StGLMesh.h"
14
+
15
+class StBndSphere;
16
+
17
+/**
18
+ * Class represents configurable UV cylinder with computed vertices, normales, texture coordinates.
19
+ */
20
+class StGLUVCylinder : public StGLMesh {
21
+
22
+        public:
23
+
24
+    /**
25
+     * Defines the UV cylinder mesh with specified parameters.
26
+     */
27
+    ST_CPPEXPORT StGLUVCylinder(const StGLVec3& theCenter,
28
+                                const float theHeight,
29
+                                const float theRadius,
30
+                                const int theRings);
31
+
32
+    /**
33
+     * Defines the UV cylinder mesh with specified parameters.
34
+     */
35
+    ST_CPPEXPORT StGLUVCylinder(const StGLVec3& theCenter,
36
+                                const float theHeight,
37
+                                const float theRadius,
38
+                                const float theAngleFrom,
39
+                                const float theAngleTo,
40
+                                const int theRings);
41
+
42
+    ST_CPPEXPORT virtual ~StGLUVCylinder();
43
+
44
+    /**
45
+     * Compute the mesh using current configuration.
46
+     */
47
+    ST_CPPEXPORT virtual bool computeMesh() ST_ATTR_OVERRIDE;
48
+
49
+    ST_LOCAL float getRadius()    const { return myRadius; }
50
+    ST_LOCAL void  setRadius(float theRadius) { myRadius = theRadius; }
51
+    ST_LOCAL float getHeight()    const { return myHeight; }
52
+    ST_LOCAL void  setHeight(float theHeight) { myHeight = theHeight; }
53
+    ST_LOCAL float getAngleFrom() const { return myAngleFrom; }
54
+    ST_LOCAL void  setAngleFrom(float theAngle) { myAngleFrom = theAngle; }
55
+    ST_LOCAL float getAngleTo()   const { return myAngleTo; }
56
+    ST_LOCAL void  setAngleTo(float theAngle) { myAngleTo = theAngle; }
57
+    ST_LOCAL float getAngle()     const { return myAngleTo - myAngleFrom; }
58
+
59
+        private:
60
+
61
+    StGLVec3 myCenter;
62
+    float    myRadius;
63
+    float    myHeight;
64
+    float    myAngleFrom;
65
+    float    myAngleTo;
66
+    int      myNbRings;
67
+
68
+};
69
+
70
+#endif //__StGLUVCylinder_h_
71
sview-17_04.tar.gz/include/StGLMesh/StGLUVSphere.h -> sview-20_08.tar.gz/include/StGLMesh/StGLUVSphere.h Changed
26
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -26,7 +26,8 @@
9
      */
10
     ST_CPPEXPORT StGLUVSphere(const StGLVec3& theCenter,
11
                               const GLfloat   theRadius,
12
-                              const size_t    theRings);
13
+                              const size_t    theRings,
14
+                              const bool      theIsHemisphere);
15
 
16
     /**
17
      * Defines the UV sphere from boundary sphere.
18
@@ -55,6 +56,7 @@
19
     StGLVec3             myCenter;
20
     GLfloat              myRadius;
21
     size_t               myRings;
22
+    bool                 myIsHemisphere;
23
 
24
 };
25
 
26
sview-17_04.tar.gz/include/StGLStereo/StFormatEnum.h -> sview-20_08.tar.gz/include/StGLStereo/StFormatEnum.h Changed
63
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -41,14 +41,20 @@
9
 enum StCubemap {
10
     StCubemap_AUTO = -1, //!< try to detect from metadata
11
     StCubemap_OFF  =  0, //!< no cubemap data
12
-    StCubemap_Packed     //!< cubemap data packed into single image frame - 6 horizontally stacked planes
13
+    StCubemap_Packed,    //!< cubemap data packed into single image frame - 6 horizontally stacked planes
14
+    StCubemap_PackedEAC  //!< cubemap data packed into single image frame (EAC layout)
15
 };
16
 
17
 enum StPanorama {
18
-    StPanorama_OFF  =  0,  //!< no cubemap data
19
-    StPanorama_Sphere,     //!< spherical panorama
20
-    StPanorama_Cubemap6_1, //!< cubemap data packed into single image frame - 6:1
21
-    StPanorama_Cubemap3_2  //!< cubemap data packed into single image frame - 3:2
22
+    StPanorama_OFF  =  0,     //!< no cubemap data
23
+    StPanorama_Sphere,        //!< spherical panorama 360 degrees - 2:1
24
+    StPanorama_Hemisphere,    //!< spherical panorama 180 degrees - 1:1
25
+    StPanorama_Cubemap6_1,    //!< cubemap data packed into single image frame - 6:1 in OpenGL enum order (px nx py ny pz nz)
26
+    StPanorama_Cubemap1_6,    //!< cubemap data packed into single image frame - 1:6 in OpenGL enum order
27
+    StPanorama_Cubemap3_2,    //!< cubemap data packed into single image frame - 3:2 in OpenGL enum order
28
+    StPanorama_Cubemap3_2ytb, //!< cubemap data packed into single image frame - 3:2 in custom order (px nz nx, ny pz py)
29
+                              //!  one row defines 3 horizontally stacked sides of the cube, and other 3 vertically stacked sides
30
+    StPanorama_Cubemap2_3ytb  //!< cubemap data packed into single image frame - 2:3 in custom order (90 counterclockwise transposed 3x2 layout)
31
 };
32
 
33
 namespace st {
34
@@ -96,8 +102,12 @@
35
      * - half,q    Anamorph suffix
36
      * or file extension:
37
      * - jps,pns   SideBySide (Right/Left order)
38
+     * @param theFileName  [in] file name to parse
39
+     * @param theToSwapJps [in] if TRUE, then JPS/PNS file extension will be treated as Left/Right instead of Right/Left
40
+     * @param theIsAnamorph [out] flag indicating anamorphic aspect ratio
41
      */
42
     ST_CPPEXPORT StFormat formatFromName(const StString& theFileName,
43
+                                         const bool      theToSwapJps,
44
                                          bool&           theIsAnamorph);
45
 
46
     /**
47
@@ -147,9 +157,15 @@
48
         } else if(theSrc1SizeX / 6 == theSrc1SizeY
49
                && theSrc2SizeX / 6 == theSrc2SizeY) {
50
             return StPanorama_Cubemap6_1;
51
+        } else if(theSrc1SizeY / 6 == theSrc1SizeX
52
+               && theSrc2SizeY / 6 == theSrc2SizeX) {
53
+            return StPanorama_Cubemap1_6;
54
         } else if(theSrc1SizeX / 3 == theSrc1SizeY / 2
55
                && theSrc2SizeX / 3 == theSrc2SizeY / 2) {
56
             return StPanorama_Cubemap3_2;
57
+        } else if(theSrc1SizeX == theSrc1SizeY
58
+               && theSrc2SizeX == theSrc2SizeY) {
59
+            return StPanorama_Hemisphere;
60
         }
61
         return StPanorama_OFF;
62
     }
63
sview-17_04.tar.gz/include/StGLStereo/StGLProjCamera.h -> sview-20_08.tar.gz/include/StGLStereo/StGLProjCamera.h Changed
75
 
1
@@ -38,6 +38,11 @@
2
     ST_CPPEXPORT StGLProjCamera();
3
 
4
     /**
5
+     * Copy constructor.
6
+     */
7
+    ST_CPPEXPORT StGLProjCamera(const StGLProjCamera& theOther);
8
+
9
+    /**
10
      * Custom projection camera.
11
      */
12
     ST_CPPEXPORT StGLProjCamera(const GLfloat theFOVy,
13
@@ -46,6 +51,19 @@
14
                                 const GLfloat theZScreen);
15
 
16
     /**
17
+     * Copy camera settings.
18
+     */
19
+    ST_CPPEXPORT void copyFrom(const StGLProjCamera& theOther);
20
+
21
+    /**
22
+     * Copy camera settings.
23
+     */
24
+    ST_LOCAL StGLProjCamera& operator=(const StGLProjCamera& theOther) {
25
+        copyFrom(theOther);
26
+        return *this;
27
+    }
28
+
29
+    /**
30
      * Get projection type.
31
      */
32
     inline bool isPerspective() const {
33
@@ -103,6 +121,7 @@
34
      */
35
     inline void setFOVy(const GLfloat theFOVy) {
36
         myFOVy = theFOVy;
37
+        updateFrustum();
38
     }
39
 
40
     /**
41
@@ -234,6 +253,21 @@
42
     }
43
 
44
     /**
45
+     * Return TRUE if custom stereoscopic projection frustum has been set.
46
+     */
47
+    ST_LOCAL bool isCustomProjection() const { return myIsCustomFrust; }
48
+
49
+    /**
50
+     * Unset custom projection.
51
+     */
52
+    ST_CPPEXPORT void resetCustomProjection();
53
+
54
+    /**
55
+     * Setup custom projection.
56
+     */
57
+    ST_CPPEXPORT void setCustomProjection(const StRectF_t& theLeft, const StRectF_t& theRight);
58
+
59
+    /**
60
      * Returns the string description for the camera.
61
      * For debug purposes...
62
      */
63
@@ -243,6 +277,11 @@
64
 
65
     StGLMatrix  myMatrix;     //!< current projection matrix
66
     StGLMatrix  myMatrixMono; //!< we store mono projection matrix to allow draw special object
67
+
68
+    StRectF_t   myVrFrustumL; //!< custom VR projection frustum, left eye
69
+    StRectF_t   myVrFrustumR; //!< custom VR projection frustum, right eye
70
+    bool        myIsCustomFrust;
71
+
72
     GLfloat     myFOVy;       //!< field of view in y-axis (degrees)
73
     GLfloat     myZoom;       //!< linear zoom factor (changes the effective FOVy value!)
74
     GLfloat     myAspect;     //!< screen aspect ratio, recomputed on window size change
75
sview-17_04.tar.gz/include/StGLStereo/StGLQuadTexture.h -> sview-20_08.tar.gz/include/StGLStereo/StGLQuadTexture.h Changed
111
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -27,35 +27,49 @@
9
     /**
10
      * @return data size in the texture.
11
      */
12
-    inline const StGLVec2& getDataSize() {
13
-        return myDataSize;
14
-    }
15
+    ST_LOCAL const StGLVec2& getDataSize() { return myDataSize; }
16
 
17
     /**
18
-     * @param theDataSize - setted data size in the texture.
19
+     * @param theDataSize - set data size in the texture.
20
      */
21
-    inline void setDataSize(const StGLVec2& theDataSize) {
22
-        myDataSize = theDataSize;
23
-    }
24
+    ST_LOCAL void setDataSize(const StGLVec2& theDataSize) { myDataSize = theDataSize; }
25
 
26
     /**
27
      * @return display aspect ratio.
28
      */
29
-    inline GLfloat getDisplayRatio() const {
30
-        return myDisplayRatio;
31
-    }
32
+    ST_LOCAL GLfloat getDisplayRatio() const { return myDisplayRatio; }
33
 
34
     /**
35
      * @param theValue - display aspect ratio.
36
      */
37
-    inline void setDisplayRatio(const GLfloat theValue) {
38
-        myDisplayRatio = theValue;
39
-    }
40
+    ST_LOCAL void setDisplayRatio(const GLfloat theValue) { myDisplayRatio = theValue; }
41
+
42
+    /**
43
+     * Returns Pixel Aspect Ratio.
44
+     */
45
+    ST_LOCAL GLfloat getPixelRatio() const { return myPAR; }
46
+
47
+    /**
48
+     * Sets Pixel Aspect Ratio.
49
+     */
50
+    ST_LOCAL void setPixelRatio(const GLfloat thePAR) { myPAR = thePAR; }
51
+
52
+    /**
53
+     * Returns packed panorama format.
54
+     */
55
+    ST_LOCAL StPanorama getPackedPanorama() const { return myPanorama; }
56
+
57
+    /**
58
+     * Sets packed panorama format.
59
+     */
60
+    ST_LOCAL void setPackedPanorama(StPanorama thePano) { myPanorama = thePano; }
61
 
62
         private:
63
 
64
-    StGLVec2 myDataSize;     //!< data size in the texture (x()=right and y()=bottom)
65
-    GLfloat  myDisplayRatio; //!< display aspect ratio
66
+    StGLVec2   myDataSize;     //!< data size in the texture (x()=right and y()=bottom)
67
+    float      myDisplayRatio; //!< display aspect ratio
68
+    float      myPAR;          //!< pixel aspect ratio
69
+    StPanorama myPanorama;     //!< packed panorama format
70
 
71
 };
72
 
73
@@ -161,7 +175,17 @@
74
      * After this call current bound texture will be undefined.
75
      */
76
     ST_CPPEXPORT void setMinMagFilter(StGLContext& theCtx,
77
-                                      const GLenum theMinMagFilter);
78
+                                      const GLenum theMinFilter,
79
+                                      const GLenum theMagFilter);
80
+
81
+    /**
82
+     * Change Min and Mag filter.
83
+     * After this call current bound texture will be undefined.
84
+     */
85
+    ST_LOCAL void setMinMagFilter(StGLContext& theCtx,
86
+                                  const GLenum theMinMagFilter) {
87
+        setMinMagFilter(theCtx, theMinMagFilter, theMinMagFilter);
88
+    }
89
 
90
         private:
91
 
92
@@ -229,7 +253,17 @@
93
      * After this call current bound texture will be undefined.
94
      */
95
     ST_CPPEXPORT void setMinMagFilter(StGLContext& theCtx,
96
-                                      const GLenum theMinMagFilter);
97
+                                      const GLenum theMinFilter,
98
+                                      const GLenum theMagFilter);
99
+
100
+    /**
101
+     * Change Min and Mag filter.
102
+     * After this call current bound texture will be undefined.
103
+     */
104
+    ST_LOCAL void setMinMagFilter(StGLContext& theCtx,
105
+                                  const GLenum theMinMagFilter) {
106
+        setMinMagFilter(theCtx, theMinMagFilter, theMinMagFilter);
107
+    }
108
 
109
         private:
110
 
111
sview-17_04.tar.gz/include/StGLStereo/StGLTextureData.h -> sview-20_08.tar.gz/include/StGLStereo/StGLTextureData.h Changed
44
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -10,6 +10,7 @@
9
 #define __StGLTextureData_h_
10
 
11
 #include <StImage/StImage.h>
12
+#include <StGLStereo/StGLTextureUploadParams.h>
13
 #include <StGLStereo/StGLQuadTexture.h>
14
 #include <StGL/StGLDeviceCaps.h>
15
 
16
@@ -38,7 +39,7 @@
17
     /**
18
      * Default constructor
19
      */
20
-    ST_CPPEXPORT StGLTextureData();
21
+    ST_CPPEXPORT StGLTextureData(const StHandle<StGLTextureUploadParams>& theUploadParams);
22
 
23
     /**
24
      * Destructor.
25
@@ -175,6 +176,10 @@
26
 
27
     ST_LOCAL void setupAttributes(StGLFrameTextures& stFrameTextures, const StImage& theImage);
28
 
29
+    ST_LOCAL void setupDataRectangle(const StImagePlane& theImagePlane,
30
+                                     const GLfloat       thePixelRatio,
31
+                                     StGLFrameTexture&   theTextureFrame);
32
+
33
         private:
34
 
35
     StGLTextureData*         myPrev;          //!< pointer to previous item in the list
36
@@ -191,6 +196,7 @@
37
     StFormat                 mySrcFormat;
38
     StCubemap                myCubemapFormat;
39
 
40
+    StHandle<StGLTextureUploadParams> myUploadParams; //!< texture streaming parameters
41
     GLsizei                  myFillFromRow;
42
     GLsizei                  myFillRows;
43
 
44
sview-17_04.tar.gz/include/StGLStereo/StGLTextureQueue.h -> sview-20_08.tar.gz/include/StGLStereo/StGLTextureQueue.h Changed
43
 
1
@@ -42,6 +42,11 @@
2
     ST_CPPEXPORT ~StGLTextureQueue();
3
 
4
     /**
5
+     * Get device capabilities.
6
+     */
7
+    ST_LOCAL const StGLDeviceCaps& getDeviceCaps() const { return myDeviceCaps; }
8
+
9
+    /**
10
      * Set device capabilities.
11
      */
12
     ST_LOCAL void setDeviceCaps(const StGLDeviceCaps& theCaps) {
13
@@ -58,6 +63,11 @@
14
     }
15
 
16
     /**
17
+     * Return texture streaming parameters.
18
+     */
19
+    ST_LOCAL StGLTextureUploadParams& getUploadParams() { return *myUploadParams; }
20
+
21
+    /**
22
      * @return input stream connection state
23
      */
24
     ST_LOCAL bool hasConnectedStream() const {
25
@@ -209,7 +219,8 @@
26
      * This function clean up only requested number of frames but prevents queue emptying.
27
      * At least one frame will remain in queue.
28
      */
29
-    ST_CPPEXPORT void drop(const size_t theCount);
30
+    ST_CPPEXPORT void drop(const size_t theCount,
31
+                           double& thePtsFront);
32
 
33
     /**
34
      * Function used to get current showed source format.
35
@@ -276,6 +287,7 @@
36
     volatile bool    myHasStream;      //!< flag indicates that some stream connected to this queue
37
 
38
     StGLDeviceCaps   myDeviceCaps;     //!< device capabilities
39
+    StHandle<StGLTextureUploadParams> myUploadParams; //!< texture streaming parameters
40
 
41
 };
42
 
43
sview-20_08.tar.gz/include/StGLStereo/StGLTextureUploadParams.h Added
41
 
1
@@ -0,0 +1,39 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#ifndef __StGLTextureUploadParams_h_
11
+#define __StGLTextureUploadParams_h_
12
+
13
+/**
14
+ * Structure holding parameters for texture uploading.
15
+ * Uploading big amounts of data onto GPU leads to frame-rate lags (specifically in case when uploading done within rendering thread);
16
+ * to smooth this effect, upload process can be split into smaller chunks.
17
+ *
18
+ * There are 4 use cases, which are sensitive to texture uploading lags:
19
+ * - GUI rendering; will be noticeable only for very large uploads.
20
+ * - 360 panorama with device orientation tracking; will be noticeable due lag on orientation update.
21
+ * - HMD output with head orientation tracking; same as panorama, but will be noticeable all time (no option disabling head tracking) and can lead to headaches.
22
+ * - Software PageFlipping (texture uploading lag might lead to missing VSync and swapping Left/Right frames).
23
+ *
24
+ * Most optimal case would be defining amount of chunks equal to amount of frames to be rendered before new (uploaded) texture should appear,
25
+ * in this case average FPS will be close to constant, which is in particular good to preserve GUI interactive.
26
+ * At the same time, uploading data within more than 1 rendering frame would add a constant time shift to video stream presented to user,
27
+ * which ideally should be also considered.
28
+ * At last, the real maximum rendering FPS naturally limited by monitor frequency, can be not achievable due to slow GPU.
29
+ */
30
+struct StGLTextureUploadParams {
31
+
32
+    int MaxUploadIterations; //!< maximum number of texture upload iterations (frames); 1 means texture should be uploaded immediately
33
+    int MaxUploadChunkMiB;   //!< maximum number of data in MiB to be uploaded within single iteration; 0 means no limit;
34
+                             //!  MaxUploadIterations is stronger limit
35
+
36
+    StGLTextureUploadParams() : MaxUploadIterations(1), MaxUploadChunkMiB(0) {}
37
+
38
+};
39
+
40
+#endif // __StGLTextureUploadParams_h_
41
sview-17_04.tar.gz/include/StGLWidgets/StGLCombobox.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLCombobox.h Changed
9
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2015-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
sview-17_04.tar.gz/include/StGLWidgets/StGLImageProgram.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLImageProgram.h Changed
135
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -20,14 +20,15 @@
10
 /**
11
  * GLSL program for Image Region widget.
12
  */
13
-class StGLImageProgram : public StGLProgramMatrix<1, 5, StGLMeshProgram> {
14
+class StGLImageProgram : public StGLProgramMatrix<1, 6, StGLMeshProgram> {
15
 
16
         public:
17
 
18
     typedef enum tagTextureFilter {
19
-        FILTER_NEAREST, //!< ugly filter
20
-        FILTER_LINEAR,  //!< linear filter
21
-        FILTER_BLEND,   //!< blend deinterlace filter
22
+        FILTER_NEAREST,   //!< ugly filter
23
+        FILTER_LINEAR,    //!< linear filter
24
+        FILTER_BLEND,     //!< blend deinterlace filter
25
+        FILTER_TRILINEAR, //!< trilinear filter (generate mip-maps)
26
     } TextureFilter;
27
 
28
     /**
29
@@ -43,11 +44,12 @@
30
      * Color conversion options in GLSL Fragment Shader.
31
      */
32
     enum FragSection {
33
-        FragSection_Main = 0, //!< section with main() function
34
-        FragSection_GetColor, //!< read color values from textures
35
-        FragSection_ToRgb,    //!< color conversion
36
-        FragSection_Correct,  //!< color correction
37
-        FragSection_Gamma,    //!< gamma correction
38
+        FragSection_Main = 0,     //!< section with main() function
39
+        FragSection_GetColor,     //!< read color values from textures
40
+        FragSection_GetTexCoords, //!< EAC texture coordinates correction
41
+        FragSection_ToRgb,        //!< color conversion
42
+        FragSection_Correct,      //!< color correction
43
+        FragSection_Gamma,        //!< gamma correction
44
         FragSection_NB
45
     };
46
 
47
@@ -70,11 +72,17 @@
48
         FragToRgb_FromGray,
49
         FragToRgb_FromXyz,
50
         FragToRgb_FromYuvFull,
51
+        FragToRgb_FromYuvaFull,
52
         FragToRgb_FromYuvMpeg,
53
+        FragToRgb_FromYuvaMpeg,
54
         FragToRgb_FromYuv9Full,
55
+        FragToRgb_FromYuva9Full,
56
         FragToRgb_FromYuv9Mpeg,
57
+        FragToRgb_FromYuva9Mpeg,
58
         FragToRgb_FromYuv10Full,
59
+        FragToRgb_FromYuva10Full,
60
         FragToRgb_FromYuv10Mpeg,
61
+        FragToRgb_FromYuva10Mpeg,
62
         FragToRgb_FromYuvNvFull,
63
         FragToRgb_FromYuvNvMpeg,
64
         FragToRgb_CUBEMAP,
65
@@ -99,6 +107,15 @@
66
         FragGamma_NB
67
     };
68
 
69
+    /**
70
+     * Texture coordinates EAC correction options in GLSL Fragment Shader.
71
+     */
72
+    enum FragTexEAC {
73
+        FragTexEAC_Off = 0,
74
+        FragTexEAC_On,
75
+        FragTexEAC_NB
76
+    };
77
+
78
         public:
79
 
80
     ST_CPPEXPORT StGLImageProgram();
81
@@ -114,6 +131,9 @@
82
     ST_CPPEXPORT void setTextureUVDataSize(StGLContext&    theCtx,
83
                                            const StGLVec4& theTexDataVec4);
84
 
85
+    ST_CPPEXPORT void setTextureADataSize(StGLContext&    theCtx,
86
+                                          const StGLVec4& theTexDataVec4);
87
+
88
     ST_CPPEXPORT void setCubeTextureFlipZ(StGLContext&    theCtx,
89
                                           bool theToFlip);
90
 
91
@@ -128,10 +148,11 @@
92
     /**
93
      * Initialize default shaders, nothing more.
94
      */
95
-    ST_CPPEXPORT virtual bool init(StGLContext&                 theCtx,
96
-                                   const StImage::ImgColorModel theColorModel,
97
-                                   const StImage::ImgColorScale theColorScale,
98
-                                   const FragGetColor           theFilter);
99
+    ST_CPPEXPORT bool init(StGLContext&                 theCtx,
100
+                           const StImage::ImgColorModel theColorModel,
101
+                           const StImage::ImgColorScale theColorScale,
102
+                           const FragGetColor           theFilter,
103
+                           const FragTexEAC theTexCoord = FragTexEAC_Off);
104
 
105
         public: //!< Properties
106
 
107
@@ -146,8 +167,10 @@
108
         private: //!< callback Slots
109
 
110
     ST_LOCAL void setupCorrection(StGLContext& theCtx);
111
-    ST_LOCAL void regToRgb(const int       thePartIndex,
112
+    ST_LOCAL void regToRgb(const StGLContext& theCtx,
113
+                           const int       thePartIndex,
114
                            const StString& theText);
115
+    ST_LOCAL void registerFragments(const StGLContext& theCtx);
116
 
117
         protected:
118
 
119
@@ -161,6 +184,7 @@
120
 
121
     StGLVarLocation uniTexMainDataLoc;
122
     StGLVarLocation uniTexUVDataLoc;
123
+    StGLVarLocation uniTexADataLoc;
124
     StGLVarLocation uniTexSizePxLoc;
125
     StGLVarLocation uniTexelSizePxLoc;
126
     StGLVarLocation uniTexCubeFlipZLoc;
127
@@ -168,6 +192,7 @@
128
     StGLVarLocation uniGammaLoc;
129
 
130
     StGLVec3        myColorScale; //!< scale filter for de-anaglyph processing
131
+    bool            myIsRegistered;
132
 
133
 };
134
 
135
sview-17_04.tar.gz/include/StGLWidgets/StGLImageRegion.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLImageRegion.h Changed
137
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2016 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -10,6 +10,7 @@
10
 #ifndef __StGLImageRegion_h_
11
 #define __StGLImageRegion_h_
12
 
13
+#include <StGLMesh/StGLUVCylinder.h>
14
 #include <StGLMesh/StGLUVSphere.h>
15
 #include <StGLMesh/StGLQuads.h>
16
 
17
@@ -18,10 +19,12 @@
18
 #include <StGLStereo/StGLTextureQueue.h>
19
 
20
 #include <StGL/StParams.h>
21
+#include <StGL/StPlayList.h>
22
 
23
+#include <StSlots/StAction.h>
24
 #include <StSettings/StEnumParam.h>
25
 
26
-class StAction;
27
+class StGLIcon;
28
 
29
 class StGLImageRegion : public StGLWidget {
30
 
31
@@ -87,6 +90,30 @@
32
                                  const bool  theUsePanningKeys);
33
 
34
     /**
35
+     * Return playlist.
36
+     */
37
+    ST_LOCAL const StHandle<StPlayList>& getPlayList() const {
38
+        return myList;
39
+    }
40
+
41
+    /**
42
+     * Set playlist.
43
+     */
44
+    ST_LOCAL void setPlayList(const StHandle<StPlayList>& theList) {
45
+        myList = theList;
46
+    }
47
+
48
+    /**
49
+     * Return icon widget displayed on swipe gesture.
50
+     */
51
+    StGLIcon* changeIconPrev() { return myIconPrev; }
52
+
53
+    /**
54
+     * Return icon widget displayed on swipe gesture.
55
+     */
56
+    StGLIcon* changeIconNext() { return myIconNext; }
57
+
58
+    /**
59
      * Setup device orientation.
60
      */
61
     ST_LOCAL void setDeviceOrientation(const StGLQuaternion& theQ) { myDeviceQuat = theQ; }
62
@@ -163,6 +190,16 @@
63
      */
64
     ST_CPPEXPORT void stglSkipFrames();
65
 
66
+    /**
67
+     * Return sample aspect ratio.
68
+     */
69
+    ST_LOCAL float getSampleRatio() const { return mySampleRatio; }
70
+
71
+    /**
72
+    * Return frame dimensions.
73
+    */
74
+    ST_LOCAL const StVec2<int>& getFrameSize() const { return myFrameSize; }
75
+
76
         public: //! @name Properties
77
 
78
     struct {
79
@@ -185,6 +222,15 @@
80
 
81
     } params;
82
 
83
+        public:  //! @name Signals
84
+
85
+    struct {
86
+        /**
87
+         * Emit new item signal.
88
+         */
89
+        StSignal<void (void )> onOpenItem;
90
+    } signals;
91
+
92
         private:
93
 
94
     /**
95
@@ -301,23 +347,40 @@
96
 
97
     ST_LOCAL void doRightUnclick(const StPointD_t& theCursorZo);
98
 
99
+    ST_LOCAL bool stglInitCube(const StGLVec4& theClampUV = StGLVec4(0.0f, 0.0f, 1.0f, 1.0f),
100
+                               const StPanorama thePano = StPanorama_OFF);
101
     ST_LOCAL void stglDrawView(unsigned int theView);
102
 
103
         private: //! @name private fields
104
 
105
     StArrayList< StHandle<StAction> >
106
                                myActions;        //!< actions list
107
+    StHandle<StPlayList>       myList;           //!< handle to playlist
108
+
109
+    StGLIcon*                  myIconPrev;       //!< icon displayed on swipe gesture
110
+    StGLIcon*                  myIconNext;       //!< icon displayed on swipe gesture
111
 
112
     StGLQuads                  myQuad;           //!< flat quad
113
-    StGLUVSphere               myUVSphere;       //!< sphere output helper class
114
+    StGLMesh                   myCube;           //!< cube for drawing cubemap
115
+    StGLVec4                   myCubeClamp;      //!< cubemap clamping vector
116
+    StPanorama                 myCubePano;       //!< cubemap panorama format
117
+    StGLUVSphere               myUVSphere;       //!< sphere mesh object
118
+    StGLUVSphere               myHemisphere;     //!< hemisphere mesh object
119
+    StGLUVCylinder             myCylinder;       //!< cylinder mesh object
120
+    StGLUVCylinder             myTheater;        //!< theater cylinder mesh object
121
     StGLProjCamera             myProjCam;        //!< copy of projection camera
122
     StGLImageProgram           myProgram;        //!< GL program to draw flat image
123
     StHandle<StGLTextureQueue> myTextureQueue;   //!< shared texture queue
124
     StPointD_t                 myClickPntZo;     //!< remembered mouse click position
125
     StTimer                    myClickTimer;     //!< timer to delay dragging action
126
+    StTimer                    myFadeTimer;      //!< timer for transition to the next file
127
+    StPointD_t                 myFadeFrom;       //!< fade starting delta
128
     StGLQuaternion             myDeviceQuat;     //!< device orientation
129
     StVirtFlags                myKeyFlags;       //!< active key flags
130
     double                     myDragDelayMs;    //!< dragging delay in milliseconds
131
+    double                     myDragDelayTmpMs; //!< temporary dragging delay
132
+    StVec2<int>                myFrameSize;      //!< frame dimensions
133
+    float                      mySampleRatio;    //!< sample aspect ratio
134
     float                      myRotAngle;       //!< rotation angle gesture progress
135
     bool                       myIsClickAborted;
136
     bool                       myToRightRotate;
137
sview-17_04.tar.gz/include/StGLWidgets/StGLMenuCheckbox.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLMenuCheckbox.h Changed
13
 
1
@@ -23,6 +23,11 @@
2
     ST_CPPEXPORT StGLMenuCheckbox(StGLMenu* theParent,
3
                                   const StHandle<StBoolParam>& theTrackedValue);
4
 
5
+    /**
6
+     * Return checkbox widget.
7
+     */
8
+    StGLCheckbox* getCheckbox() { return myCheckbox; }
9
+
10
         private: //!< callback Slots (private overriders)
11
 
12
     ST_LOCAL void doItemClick(const size_t );
13
sview-17_04.tar.gz/include/StGLWidgets/StGLMessageBox.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLMessageBox.h Changed
22
 
1
@@ -89,7 +89,7 @@
2
                                        const bool      theIsDefault = false,
3
                                        const int       theWidth = 0);
4
 
5
-    ST_CPPEXPORT virtual bool doKeyDown(const StKeyEvent& theEvent);
6
+    ST_CPPEXPORT virtual bool doKeyDown(const StKeyEvent& theEvent) ST_ATTR_OVERRIDE;
7
 
8
     ST_LOCAL int getMarginLeft()   const { return myMarginLeft; }
9
     ST_LOCAL int getMarginRight()  const { return myMarginRight; }
10
@@ -109,8 +109,9 @@
11
      */
12
     ST_CPPEXPORT void create(const StString& theTitle,
13
                              const StString& theText,
14
-                             const int       theWidth,
15
-                             const int       theHeight);
16
+                             const int  theWidth,
17
+                             const int  theHeight,
18
+                             const bool theHasButtons = true);
19
 
20
         private:   //! @name callback Slots (private overriders)
21
 
22
sview-17_04.tar.gz/include/StGLWidgets/StGLOpenFile.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLOpenFile.h Changed
94
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2015-2019 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -13,9 +13,11 @@
10
 #include <StGLWidgets/StGLMessageBox.h>
11
 #include <StGLWidgets/StGLRootWidget.h>
12
 #include <StFile/StMIMEList.h>
13
+#include <StSettings/StParam.h>
14
 
15
 class StGLMenu;
16
 class StGLMenuItem;
17
+class StGLMenuCheckbox;
18
 
19
 /**
20
  * Widget for file system navigation.
21
@@ -39,10 +41,30 @@
22
     /**
23
      * Define file filter.
24
      */
25
-    ST_CPPEXPORT void setMimeList(const StMIMEList& theFilter);
26
+    ST_CPPEXPORT void setMimeList(const StMIMEList& theFilter,
27
+                                  const StString& theName = "",
28
+                                  const bool theIsExtra = false);
29
 
30
     /**
31
-     * Open new folder.
32
+     * Check/uncheck extra files.
33
+     */
34
+    ST_LOCAL void setDisplayExtra(bool theToDisplay) {
35
+        myToShowExtraFilter->setValue(theToDisplay);
36
+    }
37
+
38
+    /**
39
+    * Add checkbox.
40
+    */
41
+    ST_CPPEXPORT StGLMenuCheckbox* addHotCheckbox(const StHandle<StBoolParam>& theParam,
42
+                                                  const StString& theName);
43
+
44
+    /**
45
+     * Add system drives to folders' list.
46
+     */
47
+    ST_CPPEXPORT void addSystemDrives();
48
+
49
+    /**
50
+     * Add item to folders' list.
51
      */
52
     ST_CPPEXPORT void addHotItem(const StString& theTarget,
53
                                  const StString& theName = "");
54
@@ -76,6 +98,11 @@
55
     ST_CPPEXPORT void doHotItemClick(const size_t theItemId);
56
 
57
     /**
58
+     * Handle filter check.
59
+     */
60
+    ST_CPPEXPORT void doFilterCheck(const bool theIsChecked);
61
+
62
+    /**
63
      * Handle item click event - just remember item id.
64
      */
65
     ST_CPPEXPORT void doFileItemClick(const size_t theItemId);
66
@@ -91,16 +118,27 @@
67
     ST_CPPEXPORT virtual bool tryUnClick(const StClickEvent& theEvent,
68
                                          bool&               theIsItemUnclicked) ST_ATTR_OVERRIDE;
69
 
70
+    /**
71
+     * Reset extension list.
72
+     */
73
+    ST_CPPEXPORT void initExtensions();
74
+
75
         protected: //! @name class fields
76
 
77
     StHandle<StGLTextureArray> myTextureFolder;
78
     StHandle<StGLTextureArray> myTextureFile;
79
     StGLTextArea*              myCurrentPath;
80
+    StGLScrollArea*            myHotListContent;
81
     StGLMenu*                  myHotList;       //!< widget containing the list of predefined libraries
82
     StGLMenu*                  myList;          //!< widget containing the file list of currently opened folder
83
+    StGLMenuCheckbox*          myMainFilterCheck;  //!< main  file filter checkbox
84
+    StGLMenuCheckbox*          myExtraFilterCheck; //!< extra file filter checkbox
85
+    StHandle<StBoolParam>      myToShowMainFilter;
86
+    StHandle<StBoolParam>      myToShowExtraFilter;
87
     StArrayList<StString>      myHotPaths;      //!< array of hot-links
88
     StHandle<StFolder>         myFolder;        //!< currently opened folder
89
     StMIMEList                 myFilter;        //!< file filter
90
+    StMIMEList                 myExtraFilter;   //!< extra file filter
91
     StArrayList<StString>      myExtensions;    //!< extensions filter
92
     StString                   myItemToLoad;    //!< new item to open
93
 
94
sview-17_04.tar.gz/include/StGLWidgets/StGLRootWidget.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLRootWidget.h Changed
60
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -410,10 +410,6 @@
10
         return myScrDispX;
11
     }
12
 
13
-    inline GLfloat getLensDist() const {
14
-        return myLensDist;
15
-    }
16
-
17
     inline void setLensDist(const GLfloat theLensDist) {
18
         myLensDist = theLensDist;
19
     }
20
@@ -451,8 +447,20 @@
21
      * @param theRect        Rectangle in window coordinates
22
      * @param theScissorRect Scissor rectangle for glScissor() call
23
      */
24
-    ST_CPPEXPORT void stglScissorRect(const StRectI_t& theRect,
25
-                                      StGLBoxPx&       theScissorRect) const;
26
+    ST_LOCAL void stglScissorRect2d(const StRectI_t& theRect,
27
+                                    StGLBoxPx& theScissorRect) const {
28
+        stglScissorRectInternal(theRect, true, theScissorRect);
29
+    }
30
+
31
+    /**
32
+     * Computes scissor rectangle in OpenGL viewport.
33
+     * @param theRect        Rectangle in window coordinates
34
+     * @param theScissorRect Scissor rectangle for glScissor() call
35
+     */
36
+    ST_LOCAL void stglScissorRect3d(const StRectI_t& theRect,
37
+                                    StGLBoxPx& theScissorRect) const {
38
+        stglScissorRectInternal(theRect, false, theScissorRect);
39
+    }
40
 
41
     /**
42
      * Append widget to destroy list.
43
@@ -485,6 +493,16 @@
44
 
45
     ST_LOCAL void setupTextures();
46
 
47
+    /**
48
+    * Computes scissor rectangle in OpenGL viewport.
49
+    * @param theRect [in] Rectangle in window coordinates
50
+    * @param theIs2d [in] 2d/3d flag
51
+    * @param theScissorRect [out] Scissor rectangle for glScissor() call
52
+    */
53
+    ST_CPPEXPORT void stglScissorRectInternal(const StRectI_t& theRect,
54
+                                              const bool theIs2d,
55
+                                              StGLBoxPx& theScissorRect) const;
56
+
57
         private:
58
 
59
     StGLSharePointer**        myShareArray;    //!< resources shared within GL context (commonly used)
60
sview-17_04.tar.gz/include/StGLWidgets/StGLScrollArea.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLScrollArea.h Changed
21
 
1
@@ -50,6 +50,11 @@
2
     }
3
 
4
     /**
5
+     * Returns TRUE if dragging has been confirmed.
6
+     */
7
+    ST_LOCAL bool hasDragged() const { return myHasDragged; }
8
+
9
+    /**
10
      * Scroll (vertically) content.
11
      * @param theDelta scroll delta
12
      * @return true if scrolling has been done
13
@@ -72,6 +77,7 @@
14
     StTimer    myFlingTimer;  //!< timer for dragging inertia
15
     double     myFlingYSpeed; //!< the dragging velocity for inertial scrolling
16
     int        myFlingYDone;  //!< already animated inertial scrolling
17
+    float      myScrollYAccum;//!< accumulated scroll event value
18
 
19
 };
20
 
21
sview-17_04.tar.gz/include/StGLWidgets/StGLSubtitles.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLSubtitles.h Changed
79
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -20,6 +20,8 @@
10
 template<>
11
 inline void StArray<StHandle <StSubItem> >::sort() {}
12
 
13
+class StGLImageRegion;
14
+
15
 /**
16
  * Subtitles widget.
17
  */
18
@@ -37,6 +39,7 @@
19
 
20
         StString     Text;  //!< active string representation
21
         StImagePlane Image; //!< active image  representation
22
+        float        Scale; //!< image scale factor
23
 
24
             public:
25
 
26
@@ -61,14 +64,17 @@
27
 
28
         public:
29
 
30
-    ST_CPPEXPORT StGLSubtitles(StGLWidget*                     theParent,
31
+    /**
32
+     * Main constructor.
33
+     */
34
+    ST_CPPEXPORT StGLSubtitles(StGLImageRegion* theParent,
35
                                const StHandle<StSubQueue>&     theSubQueue,
36
                                const StHandle<StInt32Param>&   thePlace,
37
-                               const StHandle<StFloat32Param>& theTopDY,
38
-                               const StHandle<StFloat32Param>& theBottomDY,
39
-                               const StHandle<StFloat32Param>& theFontSize,
40
-                               const StHandle<StFloat32Param>& theParallax,
41
-                               const StHandle<StEnumParam>&    theParser);
42
+                               const StHandle<StFloat32Param>& theFontSize);
43
+
44
+    /**
45
+     * Destructor.
46
+     */
47
     ST_CPPEXPORT virtual ~StGLSubtitles();
48
     ST_CPPEXPORT virtual bool stglInit() ST_ATTR_OVERRIDE;
49
     ST_CPPEXPORT virtual void stglUpdate(const StPointD_t& thePointZo,
50
@@ -86,14 +92,22 @@
51
      */
52
     ST_CPPEXPORT void setPTS(const double thePTS);
53
 
54
+        public: //! @name Properties
55
+
56
+    struct {
57
+
58
+        StHandle<StInt32Param>     Place;         //!< placement
59
+        StHandle<StFloat32Param>   TopDY;         //!< displacement
60
+        StHandle<StFloat32Param>   BottomDY;      //!< displacement
61
+        StHandle<StFloat32Param>   FontSize;      //!< font size parameter
62
+        StHandle<StFloat32Param>   Parallax;      //!< text parallax
63
+        StHandle<StEnumParam>      Parser;        //!< text parser option
64
+        StHandle<StBoolParamNamed> ToApplyStereo; //!< apply stereoscopic format of video to image subtitles
65
+
66
+    } params;
67
+
68
         private:
69
 
70
-    StHandle<StInt32Param>   myPlace;     //!< placement
71
-    StHandle<StFloat32Param> myTopDY;     //!< displacement
72
-    StHandle<StFloat32Param> myBottomDY;  //!< displacement
73
-    StHandle<StFloat32Param> myFontSize;  //!< font size parameter
74
-    StHandle<StFloat32Param> myParallax;  //!< text parallax
75
-    StHandle<StEnumParam>    myParser;    //!< text parser option
76
     StGLTexture              myTexture;   //!< texture for image-based subtitles
77
     StGLVertexBuffer         myVertBuf;   //!< vertex buffer for image-based subtitles
78
     StGLVertexBuffer         myTCrdBuf;   //!< texture coordinates buffer for image-based subtitles
79
sview-17_04.tar.gz/include/StGLWidgets/StGLTable.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLTable.h Changed
9
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2014-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2014-2017 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
sview-17_04.tar.gz/include/StGLWidgets/StGLTextArea.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLTextArea.h Changed
9
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
sview-17_04.tar.gz/include/StGLWidgets/StGLTextBorderProgram.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLTextBorderProgram.h Changed
38
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -46,12 +46,14 @@
10
                                  const StGLMatrix& theProjMat);
11
 
12
     /**
13
-     * Setup model-view matrix.
14
-     * @param theCtx      active GL context
15
-     * @param theModelMat model-view matrix
16
+     * Setup components of model-view matrix.
17
+     * @param theCtx   active GL context
18
+     * @param theDisp  translation vector
19
+     * @param theScale scale factor
20
      */
21
-    ST_CPPEXPORT void setModelMat(StGLContext&      theCtx,
22
-                                  const StGLMatrix& theModelMat);
23
+    ST_CPPEXPORT void setDisplacement(StGLContext& theCtx,
24
+                                      const StGLVec3& theDisp,
25
+                                      const float theScale);
26
 
27
     /**
28
      * Setup text color.
29
@@ -71,7 +73,7 @@
30
         private:
31
 
32
     StGLVarLocation myUniformProjMat;  //!< location of uniform variable of projection matrix
33
-    StGLVarLocation myUniformModelMat; //!< location of uniform variable of model view matrix
34
+    StGLVarLocation myUniformDispl;    //!< location of uniform variable of displacement vector
35
     StGLVarLocation myUniformColor;    //!< location of uniform variable of color value
36
 
37
 };
38
sview-17_04.tar.gz/include/StGLWidgets/StGLTextProgram.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLTextProgram.h Changed
38
 
1
@@ -1,6 +1,6 @@
2
 /**
3
  * StGLWidgets, small C++ toolkit for writing GUI using OpenGL.
4
- * Copyright © 2009-2015 Kirill Gavrilov <kirill@sview.ru>
5
+ * Copyright © 2009-2020 Kirill Gavrilov <kirill@sview.ru>
6
  *
7
  * Distributed under the Boost Software License, Version 1.0.
8
  * See accompanying file license-boost.txt or copy at
9
@@ -53,12 +53,14 @@
10
                                  const StGLMatrix& theProjMat);
11
 
12
     /**
13
-     * Setup model-view matrix.
14
-     * @param theCtx      active GL context
15
-     * @param theModelMat model-view matrix
16
+     * Setup components of model-view matrix.
17
+     * @param theCtx   active GL context
18
+     * @param theDisp  translation vector
19
+     * @param theScale scale factor
20
      */
21
-    ST_CPPEXPORT void setModelMat(StGLContext&      theCtx,
22
-                                  const StGLMatrix& theModelMat);
23
+    ST_CPPEXPORT void setDisplacement(StGLContext& theCtx,
24
+                                      const StGLVec3& theDisp,
25
+                                      const float theScale);
26
 
27
     /**
28
      * Setup text color.
29
@@ -78,7 +80,7 @@
30
         private:
31
 
32
     StGLVarLocation myUniformProjMat;  //!< location of uniform variable of projection matrix
33
-    StGLVarLocation myUniformModelMat; //!< location of uniform variable of model view matrix
34
+    StGLVarLocation myUniformDispl;    //!< location of uniform variable of displacement vector
35
     StGLVarLocation myUniformColor;    //!< location of uniform variable of color value
36
 
37
 };
38
sview-17_04.tar.gz/include/StGLWidgets/StGLWidget.h -> sview-20_08.tar.gz/include/StGLWidgets/StGLWidget.h Changed
27
 
1
@@ -52,6 +52,11 @@
2
      */
3
     ST_CPPEXPORT double perform(bool theDirUp, bool theToForce);
4
 
5
+    /**
6
+     * Return value within 0.0 - 1.0 range.
7
+     */
8
+    double getValue() const { return myValue; }
9
+
10
 private:
11
 
12
     double  myValue;    //!< value within 0.0 - 1.0 range
13
@@ -220,7 +225,12 @@
14
     /**
15
      * @param theScissorRect rectangle for OpenGL scissor test
16
      */
17
-    ST_CPPEXPORT void stglScissorRect(StGLBoxPx& theScissorRect) const;
18
+    ST_CPPEXPORT void stglScissorRect2d(StGLBoxPx& theScissorRect) const;
19
+
20
+    /**
21
+    * @param theScissorRect rectangle for OpenGL scissor test
22
+    */
23
+    ST_CPPEXPORT void stglScissorRect3d(StGLBoxPx& theScissorRect) const;
24
 
25
     /**
26
      * @param thePointZo point in Zero2One coordinates to convert
27
sview-17_04.tar.gz/include/StGLWidgets/StSubQueue.h -> sview-20_08.tar.gz/include/StGLWidgets/StSubQueue.h Changed
20
 
1
@@ -26,13 +26,15 @@
2
     StImagePlane Image;     //!< subtitle image   representation
3
     double       TimeStart; //!< PTS to show subtitle item
4
     double       TimeEnd;   //!< PTS to hide subtitle item
5
+    float        Scale;     //!< image scale factor
6
 
7
         public:
8
 
9
-    ST_LOCAL StSubItem(const double    theTimeStart,
10
-                       const double    theTimeEnd)
11
+    ST_LOCAL StSubItem(double theTimeStart,
12
+                       double theTimeEnd)
13
     : TimeStart(theTimeStart),
14
-      TimeEnd(theTimeEnd) {
15
+      TimeEnd(theTimeEnd),
16
+      Scale(1.0f) {
17
         //
18
     }
19
 
20
sview-17_04.tar.gz/include/StImage/StDevILImage.h -> sview-20_08.tar.gz/include/StImage/StDevILImage.h Changed
10
 
1
@@ -46,6 +46,8 @@
2
     ST_CPPEXPORT StDevILImage();
3
     ST_CPPEXPORT virtual ~StDevILImage();
4
 
5
+    ST_LOCAL virtual StHandle<StImageFile> createEmpty() const ST_ATTR_OVERRIDE { return new StDevILImage(); }
6
+
7
     ST_CPPEXPORT virtual void close() ST_ATTR_OVERRIDE;
8
     ST_CPPEXPORT virtual bool loadExtra(const StString& theFilePath,
9
                                         ImageType       theImageType,
10
sview-17_04.tar.gz/include/StImage/StExifDir.h -> sview-20_08.tar.gz/include/StImage/StExifDir.h Changed
15
 
1
@@ -54,10 +54,11 @@
2
             Entry.Components = 0;
3
         }
4
 
5
-        Query(DirType theType, uint16_t theTag) : Type(theType), Folder(NULL) {
6
+        Query(DirType theType, uint16_t theTag, uint16_t theFormat = 0)
7
+        : Type(theType), Folder(NULL) {
8
             Entry.ValuePtr   = NULL;
9
             Entry.Tag        = theTag;
10
-            Entry.Format     = 0;
11
+            Entry.Format     = theFormat;
12
             Entry.Components = 0;
13
         }
14
     };
15
sview-17_04.tar.gz/include/StImage/StExifTags.h -> sview-20_08.tar.gz/include/StImage/StExifTags.h Changed
9
 
1
@@ -52,6 +52,7 @@
2
     enum Image {
3
         Image_Orientation = 0x0112,
4
         Image_DateTime    = 0x0132,
5
+        Image_MakerNote   = 0x927C, // matches TAG_MAKER_NOTE
6
     };
7
 
8
     enum Fuji {
9
sview-17_04.tar.gz/include/StImage/StFreeImage.h -> sview-20_08.tar.gz/include/StImage/StFreeImage.h Changed
10
 
1
@@ -32,6 +32,8 @@
2
     ST_CPPEXPORT StFreeImage();
3
     ST_CPPEXPORT virtual ~StFreeImage();
4
 
5
+    ST_LOCAL virtual StHandle<StImageFile> createEmpty() const ST_ATTR_OVERRIDE { return new StFreeImage(); }
6
+
7
     ST_CPPEXPORT virtual void close() ST_ATTR_OVERRIDE;
8
     ST_CPPEXPORT virtual bool loadExtra(const StString& theFilePath,
9
                                         ImageType       theImageType,
10
sview-17_04.tar.gz/include/StImage/StImage.h -> sview-20_08.tar.gz/include/StImage/StImage.h Changed
29
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2019 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -54,6 +54,7 @@
9
         ImgColor_RGBA,    //!< same as RGB but has Alpha channel to perform color blending with background
10
         ImgColor_GRAY,    //!< just gray scale
11
         ImgColor_YUV,     //!< luma/brightness (Y) + chrominance (UV color plane) - widely used in cinema
12
+        ImgColor_YUVA,    //!< luma/brightness (Y) + chrominance (UV color plane) + Alpha
13
         ImgColor_XYZ,     //!< XYZ
14
         ImgColor_CMYK,    //!< Cyan, Magenta, Yellow and Black - generally used in printing process
15
         ImgColor_HSV,     //!< Hue, Saturation, Value (also known as HSB - Hue, Saturation, Brightness)
16
@@ -75,6 +76,12 @@
17
     ST_CPPEXPORT static StString formatImgColorModel(ImgColorModel theColorModel);
18
     ST_LOCAL inline StString formatImgColorModel() const { return formatImgColorModel(myColorModel); }
19
 
20
+    /**
21
+     * Format image pixel format.
22
+     * @sa stAV::PIX_FMT::getString()
23
+     */
24
+    ST_CPPEXPORT const char* formatImgPixelFormat() const;
25
+
26
         public: //! @name initializers
27
 
28
     /**
29
sview-17_04.tar.gz/include/StImage/StImageFile.h -> sview-20_08.tar.gz/include/StImage/StImageFile.h Changed
84
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2015 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -44,6 +44,7 @@
9
         ST_TYPE_HDR, //!< Radiance High Dynamic Range - .hdr extension
10
         ST_TYPE_WEBP,
11
         ST_TYPE_WEBPLL,
12
+        ST_TYPE_DDS,
13
     } ImageType;
14
 
15
     typedef enum tagImageClass {
16
@@ -51,6 +52,7 @@
17
         ST_DEVIL,
18
         ST_FREEIMAGE,
19
         ST_WEBP,
20
+        ST_STB,
21
     } ImageClass;
22
 
23
         public:
24
@@ -72,6 +74,8 @@
25
     ST_CPPEXPORT static StHandle<StImageFile> create(ImageClass      thePreferred = ST_LIBAV,
26
                                                      ImageType       theImgType = ST_TYPE_NONE);
27
 
28
+        public:
29
+
30
     /**
31
      * Empty constructor.
32
      */
33
@@ -107,11 +111,19 @@
34
         myMetadata = theDict;
35
     }
36
 
37
+    /**
38
+     * Return stereoscopic format stored in the file or StFormat_AUTO if undefined.
39
+     */
40
     ST_LOCAL StFormat getFormat() const {
41
         return mySrcFormat;
42
     }
43
 
44
     /**
45
+     * Return panorama format stored in the file or StPanorama_OFF if undefined.
46
+     */
47
+    ST_LOCAL StPanorama getPanoramaFormat() const { return mySrcPanorama; }
48
+
49
+    /**
50
      * Returns the number of frames in multi-page image.
51
      */
52
     ///virtual size_t getFramesCount() const = 0;
53
@@ -124,9 +136,9 @@
54
      * @param theDataSize  size of data in memory
55
      * @return true on success
56
      */
57
-    bool load(const StString& theFilePath,
58
-              ImageType theImageType = ST_TYPE_NONE,
59
-              uint8_t* theDataPtr = NULL, int theDataSize = 0) { return loadExtra(theFilePath, theImageType, theDataPtr, theDataSize, false); }
60
+    ST_CPPEXPORT bool load(const StString& theFilePath,
61
+                           ImageType theImageType = ST_TYPE_NONE,
62
+                           uint8_t* theDataPtr = NULL, int theDataSize = 0);
63
 
64
     /**
65
      * This virtual function should be implemented by inheritors.
66
@@ -161,11 +173,17 @@
67
                       ImageType       theImageType,
68
                       StFormat        theSrcFormat) = 0;
69
 
70
+    /**
71
+     * Create new instance of this class.
72
+     */
73
+    virtual StHandle<StImageFile> createEmpty() const = 0;
74
+
75
         protected:
76
 
77
     StDictionary myMetadata;
78
     StString     myStateDescr;
79
     StFormat     mySrcFormat;
80
+    StPanorama   mySrcPanorama;
81
 
82
 };
83
 
84
sview-17_04.tar.gz/include/StImage/StImagePlane.h -> sview-20_08.tar.gz/include/StImage/StImagePlane.h Changed
40
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2010-2016 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2010-2020 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -23,7 +23,7 @@
9
     /**
10
      * This enumeration define packed image plane formats.
11
      */
12
-    typedef enum tagFormat {
13
+    enum ImgFormat {
14
         ImgUNKNOWN = 0, //!< not supported or unknown format
15
         ImgGray    = 1, //!< 1 byte  per pixel (1-component plane, could be part of multiple-plane image)
16
         ImgGray16,      //!< 2 bytes per pixel (1-component plane)
17
@@ -41,7 +41,8 @@
18
         ImgRGBAF,       //!< 4 floats (16-bytes) RGBA image plane
19
         ImgBGRAF,       //!< same as RGBAF but with different components order
20
         ImgUV,          //!< 2 bytes packed UV image plane
21
-    } ImgFormat;
22
+    };
23
+    enum { ImgNB = ImgUV + 1 };
24
 
25
     ST_CPPEXPORT static StString formatImgFormat(ImgFormat theImgFormat);
26
     inline StString formatImgFormat() const { return formatImgFormat(myImgFormat); }
27
@@ -259,6 +260,12 @@
28
                                const bool          theIsCompact);
29
 
30
     /**
31
+     * Initialize as transposed copy.
32
+     */
33
+    ST_CPPEXPORT bool initTransposedCopy(const StImagePlane& theCopy,
34
+                                         const bool theIsClockwise);
35
+
36
+    /**
37
      * Initialize as wrapper (data will not be copied).
38
      */
39
     ST_CPPEXPORT bool initWrapper(const StImagePlane& theCopy);
40
sview-17_04.tar.gz/include/StImage/StJpegParser.h -> sview-20_08.tar.gz/include/StImage/StJpegParser.h Changed
47
 
1
@@ -75,6 +75,11 @@
2
         ST_CPPEXPORT StString getDateTime() const;
3
 
4
         /**
5
+         * Read 360Mono and 360Stereo EXIF property.
6
+         */
7
+        ST_CPPEXPORT bool get360PanoMakerNote(bool& theIsStereo) const;
8
+
9
+        /**
10
          * Reads the parallax information from EXIF (currently - only for Fujifilm MPO).
11
          * @param theParallax the parallax in per cents
12
          * @return true if tag found
13
@@ -171,6 +176,11 @@
14
     }
15
 
16
     /**
17
+     * @return XMP
18
+     */
19
+    ST_LOCAL const StString& getXMP() const { return myXMP; }
20
+
21
+    /**
22
      * @return stereo format stored in file
23
      */
24
     ST_LOCAL StFormat getSrcFormat() const {
25
@@ -178,6 +188,11 @@
26
     }
27
 
28
     /**
29
+     * Return panorama format.
30
+     */
31
+    ST_LOCAL StPanorama getPanorama() const { return myPanorama; }
32
+
33
+    /**
34
      * Parse the structure.
35
      */
36
     ST_CPPEXPORT bool parse();
37
@@ -228,7 +243,9 @@
38
                                   //!< array of offsets in image data, starting from session lenght (zero offset is invalid)
39
     StString        myComment;    //!< string stored in COM segment (directly in JPEG, NOT inside EXIF)
40
     StString        myJpsComment; //!< string stored in JPS segment
41
+    StString        myXMP;        //!< string stored in XMP segment
42
     StFormat        myStFormat;   //!< stereo format
43
+    StPanorama      myPanorama;   //!< panorama format
44
 
45
 };
46
 
47
sview-20_08.tar.gz/include/StImage/StStbImage.h Added
56
 
1
@@ -0,0 +1,54 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#ifndef __StStbImage_h_
11
+#define __StStbImage_h_
12
+
13
+#include "StImageFile.h"
14
+
15
+// define StHandle template specialization
16
+class StStbImage;
17
+ST_DEFINE_HANDLE(StStbImage, StImageFile);
18
+
19
+/**
20
+ * This class implements image load/save operations using STB library.
21
+ */
22
+class StStbImage : public StImageFile {
23
+
24
+        public:
25
+
26
+    /**
27
+     * Should be called at application start.
28
+     */
29
+    ST_CPPEXPORT static bool init();
30
+
31
+        public:
32
+
33
+    ST_CPPEXPORT StStbImage();
34
+    ST_CPPEXPORT virtual ~StStbImage();
35
+
36
+    ST_LOCAL virtual StHandle<StImageFile> createEmpty() const ST_ATTR_OVERRIDE { return new StStbImage(); }
37
+
38
+    ST_CPPEXPORT virtual void close() ST_ATTR_OVERRIDE;
39
+    ST_CPPEXPORT virtual bool loadExtra(const StString& theFilePath,
40
+                                        ImageType       theImageType,
41
+                                        uint8_t*        theDataPtr,
42
+                                        int             theDataSize,
43
+                                        bool            theIsOnlyRGB) ST_ATTR_OVERRIDE;
44
+    ST_CPPEXPORT virtual bool save(const StString& theFilePath,
45
+                                   ImageType       theImageType,
46
+                                   StFormat        theSrcFormat) ST_ATTR_OVERRIDE;
47
+
48
+
49
+        private:
50
+
51
+     void* myStbImage;
52
+
53
+};
54
+
55
+#endif //__StStbImage_h_
56
sview-17_04.tar.gz/include/StImage/StWebPImage.h -> sview-20_08.tar.gz/include/StImage/StWebPImage.h Changed
10
 
1
@@ -32,6 +32,8 @@
2
     ST_CPPEXPORT StWebPImage();
3
     ST_CPPEXPORT virtual ~StWebPImage();
4
 
5
+    ST_LOCAL virtual StHandle<StImageFile> createEmpty() const ST_ATTR_OVERRIDE { return new StWebPImage(); }
6
+
7
     ST_CPPEXPORT virtual void close() ST_ATTR_OVERRIDE;
8
     ST_CPPEXPORT virtual bool loadExtra(const StString& theFilePath,
9
                                         ImageType       theImageType,
10
sview-20_08.tar.gz/include/StJNI Added
2
 
1
+(directory)
2
sview-20_08.tar.gz/include/StJNI/StJNIEnv.h Added
68
 
1
@@ -0,0 +1,66 @@
2
+/**
3
+ * Copyright © 2019 Kirill Gavrilov <kirill@sview.ru>
4
+ *
5
+ * Distributed under the Boost Software License, Version 1.0.
6
+ * See accompanying file license-boost.txt or copy at
7
+ * http://www.boost.org/LICENSE_1_0.txt
8
+ */
9
+
10
+#ifndef __StJNIEnv_h__
11
+#define __StJNIEnv_h__
12
+
13
+#include <StStrings/StString.h>
14
+
15
+//#include <jni.h>
16
+
17
+struct _JNIEnv;
18
+struct _JavaVM;
19
+typedef _JNIEnv JNIEnv;
20
+typedef _JavaVM JavaVM;
21
+
22
+/**
23
+ * The sentry class for attaching the current thread to JavaVM.
24
+ */
25
+class StJNIEnv {
26
+
27
+        public:
28
+
29
+    /**
30
+     * Main constructor, tries to attach JavaVM to the current thread.
31
+     */
32
+    ST_CPPEXPORT StJNIEnv(JavaVM* theJavaVM);
33
+
34
+    /**
35
+     * Destructor, automatically detaches JavaVM from current thread.
36
+     * Has no effect if JavaVM has been attached to the thread before creating this sentry.
37
+     */
38
+    ST_CPPEXPORT ~StJNIEnv();
39
+
40
+    /**
41
+     * Detach from current thread right now.
42
+     * Has no effect if JavaVM has been attached to the thread before creating this sentry.
43
+     */
44
+    ST_CPPEXPORT void detach();
45
+
46
+    /**
47
+     * Cast to actual JNIEnv instance.
48
+     */
49
+    ST_LOCAL JNIEnv* operator->() const {
50
+        return myJniEnv;
51
+    }
52
+
53
+    /**
54
+     * Return true if JNI environment is NULL.
55
+     */
56
+    ST_LOCAL bool isNull() const { return myJniEnv == NULL; }
57
+
58
+        private:
59
+
60
+    JavaVM* myJavaVM;   //!< pointer to global Java VM instance
61
+    JNIEnv* myJniEnv;   //!< JNI environment for working thread
62
+    size_t  myThreadId; //!< attached thread id
63
+    bool    myToDetach; //!< flag to detach
64
+
65
+};
66
+
67
+#endif //__StJNIEnv_h__
68
sview-17_04.tar.gz/include/StSettings/StFloat32Param.h -> sview-20_08.tar.gz/include/StSettings/StFloat32Param.h Changed
42
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2016 Kirill Gavrilov
4
+ * Copyright © 2011-2017 Kirill Gavrilov
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -93,6 +93,20 @@
9
     }
10
 
11
     /**
12
+     * @return parameter format
13
+     */
14
+    ST_LOCAL const StString& getFormat() const {
15
+        return myParamFormat;
16
+    }
17
+
18
+    /**
19
+     * Set new parameter format.
20
+     */
21
+    ST_LOCAL void setFormat(const StString& theFormat) {
22
+        myParamFormat = theFormat;
23
+    }
24
+
25
+    /**
26
      * Return true if parameter defines minimum value limit.
27
      */
28
     ST_LOCAL bool hasMinValue() const {
29
@@ -330,7 +344,12 @@
30
 
31
     StString myParamKey;    //!< parameter key (id)
32
     StString myParamName;   //!< parameter name (label)
33
+    StString myParamFormat; //!< parameter format
34
 
35
 };
36
 
37
+// define StHandle template specialization
38
+ST_DEFINE_HANDLE(StParam<float>, StParamBase);
39
+ST_DEFINE_HANDLE(StFloat32Param, StParam<float>);
40
+
41
 #endif // __StFloat32Param_h_
42
sview-17_04.tar.gz/include/StSlots/StAction.h -> sview-20_08.tar.gz/include/StSlots/StAction.h Changed
128
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2013 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2013-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -39,75 +39,75 @@
9
     virtual void doTrigger(const StEvent* theEvent) = 0;
10
 
11
     /**
12
-     * @return hot key 1 to trigger action
13
+     * @return hot key to trigger action
14
      */
15
-    ST_LOCAL unsigned int getHotKey1() const {
16
-        return myHotKey1;
17
+    ST_LOCAL unsigned int getHotKey(int theIndex) const {
18
+        ST_DEBUG_ASSERT(theIndex >= 0 && theIndex <= 1)
19
+        return myHotKeys[theIndex];
20
     }
21
 
22
     /**
23
      * @return hot key 1 to trigger action
24
      */
25
-    ST_LOCAL unsigned int& changeHotKey1() {
26
-        return myHotKey1;
27
+    ST_LOCAL unsigned int getHotKey1() const { return myHotKeys[0]; }
28
+
29
+    /**
30
+     * @return hot key 1 to trigger action
31
+     */
32
+    ST_LOCAL unsigned int& changeHotKey1() { return myHotKeys[0]; }
33
+
34
+    /**
35
+     * @param theKey hot key to trigger action
36
+     */
37
+    ST_LOCAL void setHotKey(int theIndex, unsigned int theKey) {
38
+        ST_DEBUG_ASSERT(theIndex >= 0 && theIndex <= 1)
39
+        myHotKeys[theIndex] = theKey;
40
     }
41
 
42
     /**
43
      * @param theKey hot key 1 to trigger action
44
      */
45
-    ST_LOCAL void setHotKey1(unsigned int theKey) {
46
-        myHotKey1 = theKey;
47
-    }
48
+    ST_LOCAL void setHotKey1(unsigned int theKey) { myHotKeys[0] = theKey; }
49
 
50
     /**
51
      * Default value of hot key 1.
52
      */
53
-    ST_LOCAL unsigned int getDefaultHotKey1() const {
54
-        return myDefaultHotKey1;
55
-    }
56
+    ST_LOCAL unsigned int getDefaultHotKey1() const { return myHotKeysDef[0]; }
57
 
58
     /**
59
      * @param theKey default value of hot key 1
60
      */
61
     ST_LOCAL void setDefaultHotKey1(unsigned int theKey) {
62
-        myDefaultHotKey1 = theKey;
63
-        myHotKey1        = theKey;
64
+        myHotKeysDef[0] = theKey;
65
+        myHotKeys[0]    = theKey;
66
     }
67
 
68
     /**
69
      * @return hot key 2 to trigger action
70
      */
71
-    ST_LOCAL unsigned int getHotKey2() const {
72
-        return myHotKey2;
73
-    }
74
+    ST_LOCAL unsigned int getHotKey2() const { return myHotKeys[1]; }
75
 
76
     /**
77
      * @return hot key 2 to trigger action
78
      */
79
-    ST_LOCAL unsigned int& changeHotKey2() {
80
-        return myHotKey2;
81
-    }
82
+    ST_LOCAL unsigned int& changeHotKey2() { return myHotKeys[1]; }
83
 
84
     /**
85
      * @param theKey hot key 2 to trigger action
86
      */
87
-    ST_LOCAL void setHotKey2(unsigned int theKey) {
88
-        myHotKey2 = theKey;
89
-    }
90
+    ST_LOCAL void setHotKey2(unsigned int theKey) { myHotKeys[1] = theKey; }
91
 
92
     /**
93
      * Default value of hot key 2.
94
      */
95
-    ST_LOCAL unsigned int getDefaultHotKey2() const {
96
-        return myDefaultHotKey2;
97
-    }
98
+    ST_LOCAL unsigned int getDefaultHotKey2() const { return myHotKeysDef[1]; }
99
 
100
     /**
101
      * @param theKey default value of hot key 2
102
      */
103
     ST_LOCAL void setDefaultHotKey2(unsigned int theKey) {
104
-        myDefaultHotKey2 = theKey;
105
-        myHotKey2        = theKey;
106
+        myHotKeysDef[1] = theKey;
107
+        myHotKeys[1]    = theKey;
108
     }
109
 
110
     /**
111
@@ -133,12 +133,10 @@
112
 
113
         protected:
114
 
115
-    StString     myName;           //!< action name
116
-    unsigned int myHotKey1;        //!< key combination to execute action
117
-    unsigned int myHotKey2;        //!< key combination to execute action (extra)
118
-    unsigned int myDefaultHotKey1; //!< default value of hot-key1
119
-    unsigned int myDefaultHotKey2; //!< default value of hot-key2
120
-    bool         myToHoldKey;      //!< this action process key hold event
121
+    StString     myName;          //!< action name
122
+    unsigned int myHotKeys[2];    //!< key combination to execute action
123
+    unsigned int myHotKeysDef[2]; //!< default value of hot-key1
124
+    bool         myToHoldKey;     //!< this action process key hold event
125
 
126
 };
127
 
128
sview-17_04.tar.gz/include/StStrings/StStringStream.h -> sview-20_08.tar.gz/include/StStrings/StStringStream.h Changed
17
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2011-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2011-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -20,7 +20,7 @@
9
     #if defined(_WIN32)
10
         #define ST_NO_XLOCALE
11
         #warning xlocale is not supported by compiler!
12
-    #else
13
+    #elif !defined(__GLIBC__)
14
         #include <xlocale.h>
15
     #endif
16
 #endif
17
sview-17_04.tar.gz/include/StStrings/StStringUnicode.h -> sview-20_08.tar.gz/include/StStrings/StStringUnicode.h Changed
13
 
1
@@ -353,6 +353,11 @@
2
     StStringUnicode unquoted() const;
3
 
4
     /**
5
+     * Cut off all leading space characters.
6
+     */
7
+    void leftAdjust();
8
+
9
+    /**
10
      * Cut off all trailing space characters.
11
      */
12
     void rightAdjust();
13
sview-17_04.tar.gz/include/StStrings/StStringUnicode.inl -> sview-20_08.tar.gz/include/StStrings/StStringUnicode.inl Changed
104
 
1
@@ -181,14 +181,7 @@
2
     this->Size   = 0;
3
     this->Length = 0;
4
     char aBuff[32];
5
-#if defined(_MSC_VER)
6
-    stsprintf(aBuff, 32, "%I64i", theInt64);
7
-#elif (defined(_WIN64) || defined(__WIN64__)\
8
-   ||  defined(_LP64)  || defined(__LP64__))
9
-    stsprintf(aBuff, 32, "%li",   theInt64);
10
-#else
11
-    stsprintf(aBuff, 32, "%lli",  theInt64);
12
-#endif
13
+    stsprintf(aBuff, 32, "%" PRId64, theInt64);
14
     fromUnicode(aBuff);
15
 }
16
 
17
@@ -198,14 +191,7 @@
18
     this->Size   = 0;
19
     this->Length = 0;
20
     char aBuff[32];
21
-#if defined(_MSC_VER)
22
-    stsprintf(aBuff, 32, "%I64u", theUInt64);
23
-#elif (defined(_WIN64) || defined(__WIN64__)\
24
-   ||  defined(_LP64)  || defined(__LP64__))
25
-    stsprintf(aBuff, 32, "%lu",   theUInt64);
26
-#else
27
-    stsprintf(aBuff, 32, "%llu",  theUInt64);
28
-#endif
29
+    stsprintf(aBuff, 32, "%" PRIu64, theUInt64);
30
     fromUnicode(aBuff);
31
 }
32
 
33
@@ -216,14 +202,7 @@
34
     this->Size   = 0;
35
     this->Length = 0;
36
     char aBuff[32];
37
-#if defined(_MSC_VER)
38
-    stsprintf(aBuff, 32, "%I64i", theInt64);
39
-#elif (defined(_WIN64) || defined(__WIN64__)\
40
-   ||  defined(_LP64)  || defined(__LP64__))
41
-    stsprintf(aBuff, 32, "%li",   theInt64);
42
-#else
43
-    stsprintf(aBuff, 32, "%lli",  theInt64);
44
-#endif
45
+    stsprintf(aBuff, 32, "%" PRId64,  (int64_t )theInt64);
46
     fromUnicode(aBuff);
47
 }
48
 
49
@@ -233,14 +212,7 @@
50
     this->Size   = 0;
51
     this->Length = 0;
52
     char aBuff[32];
53
-#if defined(_MSC_VER)
54
-    stsprintf(aBuff, 32, "%I64u", theUInt64);
55
-#elif (defined(_WIN64) || defined(__WIN64__)\
56
-   ||  defined(_LP64)  || defined(__LP64__))
57
-    stsprintf(aBuff, 32, "%lu",   theUInt64);
58
-#else
59
-    stsprintf(aBuff, 32, "%llu",  theUInt64);
60
-#endif
61
+    stsprintf(aBuff, 32, "%" PRIu64, (uint64_t )theUInt64);
62
     fromUnicode(aBuff);
63
 }
64
 #endif
65
@@ -713,9 +685,13 @@
66
 template<typename Type> inline
67
 StStringUnicode<Type> StStringUnicode<Type>::replace(const StStringUnicode<Type>& theSubString,
68
                                                      const StStringUnicode<Type>& theReplacer) const {
69
-    if(theSubString.isEmpty() || this->isEmpty() || theSubString.Size >= this->Size) {
70
+    if(theSubString.isEmpty() || this->isEmpty() || theSubString.Size > this->Size) {
71
         // just make a copy
72
         return *this;
73
+    } else if(theSubString.Size == this->Size) {
74
+        if(theSubString.isEquals(*this)) {
75
+            return theReplacer;
76
+        }
77
     }
78
     StUtfIterator<Type> anIter(this->String);
79
     StStringUnicode<Type> aResult;
80
@@ -761,6 +737,23 @@
81
 }
82
 
83
 template<typename Type> inline
84
+void StStringUnicode<Type>::leftAdjust() {
85
+    if(this->Length == 0) {
86
+        return;
87
+    }
88
+    for(size_t anIter = 0; anIter < this->Size / sizeof(Type); ++anIter) {
89
+      if(this->String[anIter] != (Type )' '
90
+      && this->String[anIter] != (Type )'\t') {
91
+          if(anIter != 0) {
92
+              StStringUnicode<Type> aCopy(&this->String[anIter]);
93
+              *this = aCopy;
94
+          }
95
+          return;
96
+      }
97
+    }
98
+}
99
+
100
+template<typename Type> inline
101
 void StStringUnicode<Type>::rightAdjust() {
102
     if(this->Length == 0) {
103
         return;
104
sview-17_04.tar.gz/include/StStrings/StUtfIterator.h -> sview-20_08.tar.gz/include/StStrings/StUtfIterator.h Changed
10
 
1
@@ -149,7 +149,7 @@
2
     inline const Type* getBufferNext() const { return myPosNext; }
3
 
4
     /**
5
-     * Return the index displacement from iterator intialization.
6
+     * Return the index displacement from iterator initialization.
7
      */
8
     inline size_t getIndex() const {
9
         return myCharIndex;
10
sview-17_04.tar.gz/include/StTemplates/StRect.h -> sview-20_08.tar.gz/include/StTemplates/StRect.h Changed
9
 
1
@@ -289,6 +289,7 @@
2
 
3
 typedef StRect<int>    StRectI_t;
4
 typedef StRect<double> StRectD_t;
5
+typedef StRect<float>  StRectF_t;
6
 
7
 /**
8
  * Simple structure to define rectangular margins.
9
sview-17_04.tar.gz/include/StTemplates/StTemplates.h -> sview-20_08.tar.gz/include/StTemplates/StTemplates.h Changed
15
 
1
@@ -36,13 +36,6 @@
2
     return (TypePtr )::stMemAllocZeroAligned(bytesCount, align);
3
 }
4
 
5
-template<typename TypePtr>
6
-inline TypePtr stMemReallocAligned(TypePtr ptrAligned,
7
-                                   const size_t& bytesCount,
8
-                                   const size_t& align = ST_ALIGNMENT) {
9
-    return (TypePtr )::stMemReallocAligned(ptrAligned, bytesCount, align);
10
-}
11
-
12
 /**
13
  * Auxiliary functions.
14
  */
15
sview-17_04.tar.gz/include/StTemplates/StVec2.h -> sview-20_08.tar.gz/include/StTemplates/StVec2.h Changed
45
 
1
@@ -234,6 +234,43 @@
2
                       v[1] / theInvFactor);
3
     }
4
 
5
+    /**
6
+     * Return component-wise minimum of two vectors.
7
+     */
8
+    StVec2 cwiseMin(const StVec2& theVec) const {
9
+        return StVec2(v[0] < theVec.v[0] ? v[0] : theVec.v[0],
10
+                      v[1] < theVec.v[1] ? v[1] : theVec.v[1]);
11
+    }
12
+
13
+    /**
14
+     * Return component-wise maximum of two vectors.
15
+     */
16
+    StVec2 cwiseMax(const StVec2& theVec) const {
17
+        return StVec2(v[0] > theVec.v[0] ? v[0] : theVec.v[0],
18
+                      v[1] > theVec.v[1] ? v[1] : theVec.v[1]);
19
+    }
20
+
21
+    /**
22
+     * Compute component-wise modulus of the vector.
23
+     */
24
+    StVec2 cwiseAbs() const {
25
+        return StVec2(std::abs(v[0]), std::abs(v[1]));
26
+    }
27
+
28
+    /**
29
+     * Compute maximum component of the vector.
30
+     */
31
+    Element_t maxComp() const {
32
+        return v[0] > v[1] ? v[0] : v[1];
33
+    }
34
+
35
+    /**
36
+     * Compute minimum component of the vector.
37
+     */
38
+    Element_t minComp() const {
39
+        return v[0] < v[1] ? v[0] : v[1];
40
+    }
41
+
42
 };
43
 
44
 // help structures
45
sview-17_04.tar.gz/include/StTemplates/StVec3.h -> sview-20_08.tar.gz/include/StTemplates/StVec3.h Changed
49
 
1
@@ -306,6 +306,47 @@
2
     }
3
 
4
     /**
5
+     * Return component-wise minimum of two vectors.
6
+     */
7
+    StVec3 cwiseMin(const StVec3& theVec) const {
8
+        return StVec3(v[0] < theVec.v[0] ? v[0] : theVec.v[0],
9
+                      v[1] < theVec.v[1] ? v[1] : theVec.v[1],
10
+                      v[2] < theVec.v[2] ? v[2] : theVec.v[2]);
11
+    }
12
+
13
+    /**
14
+     * Return component-wise maximum of two vectors.
15
+     */
16
+    StVec3 cwiseMax(const StVec3& theVec) const {
17
+        return StVec3(v[0] > theVec.v[0] ? v[0] : theVec.v[0],
18
+                      v[1] > theVec.v[1] ? v[1] : theVec.v[1],
19
+                      v[2] > theVec.v[2] ? v[2] : theVec.v[2]);
20
+    }
21
+
22
+    /**
23
+     * Return component-wise modulus of the vector.
24
+     */
25
+    StVec3 cwiseAbs() const {
26
+        return StVec3(std::abs (v[0]), std::abs (v[1]), std::abs (v[2]));
27
+    }
28
+
29
+    /**
30
+     * Return maximum component of the vector.
31
+     */
32
+    Element_t maxComp() const {
33
+        return v[0] > v[1] ? (v[0] > v[2] ? v[0] : v[2])
34
+                           : (v[1] > v[2] ? v[1] : v[2]);
35
+    }
36
+
37
+    /**
38
+     * Return minimum component of the vector.
39
+     */
40
+    Element_t minComp() const {
41
+        return v[0] < v[1] ? (v[0] < v[2] ? v[0] : v[2])
42
+                           : (v[1] < v[2] ? v[1] : v[2]);
43
+    }
44
+
45
+    /**
46
      * Compute linear interpolation between to vectors.
47
      * @param theT (const Element_t ) - interpolation coefficient 0..1;
48
      * @return interpolation result.
49
sview-17_04.tar.gz/include/StTemplates/StVec4.h -> sview-20_08.tar.gz/include/StTemplates/StVec4.h Changed
53
 
1
@@ -290,6 +290,51 @@
2
         return StString('(') + x() + "; " + y() + "; " + z() + "; " + w() + ')';
3
     }
4
 
5
+    /**
6
+     * Return component-wise minimum of two vectors.
7
+     */
8
+    StVec4 cwiseMin(const StVec4& theVec) const {
9
+        return StVec4(v[0] < theVec.v[0] ? v[0] : theVec.v[0],
10
+                      v[1] < theVec.v[1] ? v[1] : theVec.v[1],
11
+                      v[2] < theVec.v[2] ? v[2] : theVec.v[2],
12
+                      v[3] < theVec.v[3] ? v[3] : theVec.v[3]);
13
+    }
14
+
15
+    /**
16
+     * Return component-wise maximum of two vectors.
17
+     */
18
+    StVec4 cwiseMax(const StVec4& theVec) const {
19
+        return StVec4(v[0] > theVec.v[0] ? v[0] : theVec.v[0],
20
+                      v[1] > theVec.v[1] ? v[1] : theVec.v[1],
21
+                      v[2] > theVec.v[2] ? v[2] : theVec.v[2],
22
+                      v[3] > theVec.v[3] ? v[3] : theVec.v[3]);
23
+    }
24
+
25
+    /**
26
+     * Return component-wise modulus of the vector.
27
+     */
28
+    StVec4 cwiseAbs() const {
29
+        return StVec4(std::abs (v[0]), std::abs (v[1]), std::abs (v[2]), std::abs (v[3]));
30
+    }
31
+
32
+    /**
33
+     * Return maximum component of the vector.
34
+     */
35
+    Element_t maxComp() const {
36
+        const Element_t aMax1 = v[0] > v[1] ? v[0] : v[1];
37
+        const Element_t aMax2 = v[2] > v[3] ? v[2] : v[3];
38
+        return aMax1 > aMax2 ? aMax1 : aMax2;
39
+    }
40
+
41
+    /**
42
+     * Return minimum component of the vector.
43
+     */
44
+    Element_t minComp() const {
45
+        const Element_t aMin1 = v[0] < v[1] ? v[0] : v[1];
46
+        const Element_t aMin2 = v[2] < v[3] ? v[2] : v[3];
47
+        return aMin1 < aMin2 ? aMin1 : aMin2;
48
+    }
49
+
50
 };
51
 
52
 /**
53
sview-17_04.tar.gz/include/StThreads/StResourceManager.h -> sview-20_08.tar.gz/include/StThreads/StResourceManager.h Changed
9
 
1
@@ -93,6 +93,7 @@
2
      */
3
     enum FolderId {
4
         FolderId_SdCard,
5
+        FolderId_Documents,
6
         FolderId_Downloads,
7
         FolderId_Pictures,
8
         FolderId_Photos,
9
sview-17_04.tar.gz/include/StThreads/StThread.h -> sview-20_08.tar.gz/include/StThreads/StThread.h Changed
10
 
1
@@ -1,7 +1,7 @@
2
 /**
3
  * This is a header for threads creating/manipulating.
4
  * (redefinition for WinAPI and POSIX threads)
5
- * Copyright © 2008-2013 Kirill Gavrilov <kirill@sview.ru>
6
+ * Copyright © 2008-2017 Kirill Gavrilov <kirill@sview.ru>
7
  *
8
  * Distributed under the Boost Software License, Version 1.0.
9
  * See accompanying file license-boost.txt or copy at
10
sview-17_04.tar.gz/include/StThreads/StTimer.h -> sview-20_08.tar.gz/include/StThreads/StTimer.h Changed
34
 
1
@@ -49,10 +49,11 @@
2
      * Just start the timer again.
3
      */
4
     void resume() {
5
-        stMemSet(&myCounterStart, 0, sizeof(myCounterStart));
6
-        myIsPaused = false;
7
-
8
-        fillCounter(myCounterStart);
9
+        if(myIsPaused) {
10
+            stMemSet(&myCounterStart, 0, sizeof(myCounterStart));
11
+            myIsPaused = false;
12
+            fillCounter(myCounterStart);
13
+        }
14
     }
15
 
16
     /**
17
@@ -75,10 +76,12 @@
18
      * Pause the timer (freeze current timestamp).
19
      */
20
     void pause() {
21
-        // increment our timer value
22
-        myTimeInMicroSec += getElapsedTimeFromLastStartInMicroSec();
23
-        // set timer paused flag
24
-        myIsPaused = true;
25
+        if(!myIsPaused) {
26
+            // increment our timer value
27
+            myTimeInMicroSec += getElapsedTimeFromLastStartInMicroSec();
28
+            // set timer paused flag
29
+            myIsPaused = true;
30
+        }
31
     }
32
 
33
     /**
34
sview-17_04.tar.gz/include/stTypes.h -> sview-20_08.tar.gz/include/stTypes.h Changed
129
 
1
@@ -1,5 +1,5 @@
2
 /**
3
- * Copyright © 2009-2014 Kirill Gavrilov <kirill@sview.ru>
4
+ * Copyright © 2009-2017 Kirill Gavrilov <kirill@sview.ru>
5
  *
6
  * Distributed under the Boost Software License, Version 1.0.
7
  * See accompanying file license-boost.txt or copy at
8
@@ -47,14 +47,31 @@
9
     #define ST_ATTR_DEPRECATED
10
 #endif
11
 
12
+// Disable deprecation warnings.
13
+#if defined(__ICL) || defined (__INTEL_COMPILER)
14
+    #define ST_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:1478))
15
+    #define ST_ENABLE_DEPRECATION_WARNINGS  __pragma(warning(pop))
16
+#elif defined(_MSC_VER)
17
+    #define ST_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:4996))
18
+    #define ST_ENABLE_DEPRECATION_WARNINGS  __pragma(warning(pop))
19
+#elif (defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || defined(__clang__)
20
+    // available since at least gcc 4.2 (maybe earlier), however only gcc 4.6+ supports this pragma inside the function body
21
+    // CLang also supports this gcc syntax (in addition to "clang diagnostic ignored")
22
+    #define ST_DISABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
23
+    #define ST_ENABLE_DEPRECATION_WARNINGS  _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"")
24
+#else
25
+    #define ST_DISABLE_DEPRECATION_WARNINGS
26
+    #define ST_ENABLE_DEPRECATION_WARNINGS
27
+#endif
28
+
29
 #if defined(__cplusplus) && (__cplusplus >= 201100L)
30
-  // part of C++11 standard
31
-  #define ST_ATTR_OVERRIDE override
32
+    // part of C++11 standard
33
+    #define ST_ATTR_OVERRIDE override
34
 #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
35
-  // versions before VS2012 emits warning as MSVC-specific extension
36
-  #define ST_ATTR_OVERRIDE override
37
+    // versions before VS2012 emits warning as MSVC-specific extension
38
+    #define ST_ATTR_OVERRIDE override
39
 #else
40
-  #define ST_ATTR_OVERRIDE
41
+    #define ST_ATTR_OVERRIDE
42
 #endif
43
 
44
 #if defined(_MSC_VER)
45
@@ -67,6 +84,32 @@
46
 #include <cstddef>     // size_t, NULL
47
 #include <cstdlib>
48
 #include <cstring>     // for memcpy
49
+
50
+#if(defined(_MSC_VER) && (_MSC_VER < 1800))
51
+    // only Visual Studio 2013+ (vc12) provides <cinttypes> header
52
+    #define PRId64 "I64d"
53
+    #define PRIu64 "I64u"
54
+    #define SCNd64 "I64d"
55
+    #define SCNu64 "I64u"
56
+    #ifdef _WIN64
57
+        #define PRIdPTR "I64d"
58
+        #define PRIuPTR "I64u"
59
+        #define SCNdPTR "I64d"
60
+        #define SCNuPTR "I64u"
61
+    #else
62
+        #define PRIdPTR "d"
63
+        #define PRIuPTR "u"
64
+        #define SCNdPTR "d"
65
+        #define SCNuPTR "u"
66
+    #endif
67
+#else
68
+    // use <inttypes.h< (C99) instead of <cinttypes> (C++11) for compatibility
69
+    #ifndef __STDC_FORMAT_MACROS
70
+        #define __STDC_FORMAT_MACROS
71
+    #endif
72
+    #include <inttypes.h>
73
+#endif
74
+
75
 #if defined(__i386) || defined(__x86_64) || defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)
76
     #include <xmmintrin.h> // for memory alignment
77
 #endif
78
@@ -355,10 +398,16 @@
79
                                const size_t& theAlign = ST_ALIGNMENT) {
80
 #if defined(_MSC_VER)
81
     return _aligned_malloc(theNbBytes, theAlign);
82
-#elif defined(__ANDROID__)
83
+#elif defined(__ANDROID__) || defined(__QNX__)
84
     return memalign(theAlign, theNbBytes);
85
-#else
86
+#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && (defined(__i386) || defined(__x86_64)))
87
     return _mm_malloc(theNbBytes, theAlign);
88
+#else
89
+    void* aPtr;
90
+    if(posix_memalign(&aPtr, theAlign, theNbBytes)) {
91
+        return NULL;
92
+    }
93
+    return aPtr;
94
 #endif
95
 }
96
 
97
@@ -374,16 +423,6 @@
98
     return aPtr;
99
 }
100
 
101
-inline void* stMemReallocAligned(void* thePtrAligned, const size_t& theNbBytes,
102
-                                 const size_t& theAlign = ST_ALIGNMENT) {
103
-#if defined(_MSC_VER)
104
-    return _aligned_realloc(thePtrAligned, theNbBytes, theAlign);
105
-#else
106
-    /// TODO (Kirill Gavrilov#4) what should we call here???
107
-    return realloc(thePtrAligned, theNbBytes);
108
-#endif
109
-}
110
-
111
 /**
112
  * Deallocate space in memory.
113
  * @param ptr (void* ) - pointer to a memory block previously allocated with stMemAllocAligned() to be deallocated.
114
@@ -391,10 +430,12 @@
115
 inline void stMemFreeAligned(void* thePtrAligned) {
116
 #if defined(_MSC_VER)
117
     _aligned_free(thePtrAligned);
118
-#elif defined(__ANDROID__)
119
+#elif defined(__ANDROID__) || defined(__QNX__)
120
     free(thePtrAligned);
121
-#else
122
+#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && (defined(__i386) || defined(__x86_64)))
123
     _mm_free(thePtrAligned);
124
+#else
125
+    free(thePtrAligned);
126
 #endif
127
 }
128
 
129
sview-17_04.tar.gz/include/stconfig.conf -> sview-20_08.tar.gz/include/stconfig.conf Changed
22
 
1
@@ -35,6 +35,9 @@
2
     #define ST_DEBUG_LOG_TO_FILE "sView.log"
3
 #endif
4
 
5
+// notify about updates available on sview.ru
6
+#define ST_UPDATES_CHECK
7
+
8
 // This is TimeBomb flag
9
 // must be unset for release
10
 #ifndef ST_TIMEBOMB
11
@@ -69,6 +72,9 @@
12
 // Web UI using lightweight server mongoose
13
 #define ST_HAVE_MONGOOSE
14
 
15
-//#define ST_HAVE_LIBOVR
16
+// enable OpenVR on Windows by default
17
+#ifdef _WIN32
18
+    #define ST_HAVE_OPENVR
19
+#endif
20
 
21
 #endif //__stConfig_conf_
22
sview-17_04.tar.gz/sview/AndroidManifest.xml -> sview-20_08.tar.gz/sview/AndroidManifest.xml Changed
49
 
1
@@ -1,18 +1,25 @@
2
 <?xml version="1.0" encoding="utf-8"?>
3
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
4
           package="com.sview"
5
-          android:versionCode="16"
6
-          android:versionName="16.12"
7
+          android:versionCode="44"
8
+          android:versionName="20.01"
9
           android:installLocation="auto">
10
     <application android:label="@string/app_name"
11
                  android:hasCode="true"
12
                  android:icon="@drawable/ic_launcher">
13
         <uses-library android:name="com.s3dv.s3dvsurface" android:required="false" />
14
+
15
+        <!-- Movie Player foreground service for background audio playback  -->
16
+        <service android:name="com.sview.StMovieService"
17
+                 android:exported="false"
18
+                 android:description="@string/app_movie_service_desc" />
19
+
20
         <!-- Movie Player -->
21
         <activity android:name="com.sview.StMovieActivity"
22
                   android:label="@string/app_movie_name"
23
                   android:launchMode="singleTask"
24
                   android:alwaysRetainTaskState="true"
25
+                  android:resizeableActivity="true"
26
                   android:configChanges="orientation|keyboardHidden|screenSize"
27
                   android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
28
                   <!-- android:documentLaunchMode="always" - available since Android 5.0 -->
29
@@ -171,6 +178,7 @@
30
         <activity android:name="com.sview.StImageActivity"
31
                   android:label="@string/app_image_name"
32
                   android:launchMode="singleTask"
33
+                  android:resizeableActivity="true"
34
                   android:configChanges="orientation|keyboardHidden|screenSize"
35
                   android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
36
                   <!-- android:documentLaunchMode="always" - available since Android 5.0 -->
37
@@ -227,8 +235,10 @@
38
         <activity android:name="com.sview.CrashReportActivity" android:label="@string/app_crash_name" android:configChanges="orientation|keyboardHidden"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>
39
     </application>
40
 
41
-    <uses-sdk android:minSdkVersion="15" />
42
+    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="28" />
43
     <uses-feature android:glEsVersion="0x00020000"/>
44
     <uses-permission android:name="android.permission.INTERNET" />
45
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
46
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
47
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
48
 </manifest> 
49
sview-17_04.tar.gz/sview/Contents/Info.plist -> sview-20_08.tar.gz/sview/Contents/Info.plist Changed
19
 
1
@@ -633,7 +633,7 @@
2
    <key>CFBundleExecutable</key>
3
    <string>sView</string>
4
    <key>CFBundleGetInfoString</key>
5
-   <string>Copyright © Kirill Gavrilov, 2007-2017</string>
6
+   <string>Copyright © Kirill Gavrilov, 2007-2020</string>
7
    <key>CFBundleIdentifier</key>
8
    <string>com.sView</string>
9
    <key>CFBundleInfoDictionaryVersion</key>
10
@@ -665,7 +665,7 @@
11
    <key>DTXcodeBuild</key>
12
    <string>10M2518</string>
13
    <key>LSMinimumSystemVersion</key>
14
-   <string>10.6</string>
15
+   <string>10.10</string>
16
    <key>NSMainNibFile</key>
17
    <string>MainMenu</string>
18
    <key>NSPrincipalClass</key>
19
sview-17_04.tar.gz/sview/Resources/English.lproj/MainMenu.xib -> sview-20_08.tar.gz/sview/Resources/English.lproj/MainMenu.xib Changed
10
 
1
@@ -228,7 +228,7 @@
2
                            <object class="NSTextFieldCell" key="NSCell" id="955175397">
3
                                <int key="NSCellFlags">70385217</int>
4
                                <int key="NSCellFlags2">138544128</int>
5
-                               <string key="NSContents">Copyright © Kirill Gavrilov, 2007-2017www.sview.ru</string>
6
+                               <string key="NSContents">Copyright © Kirill Gavrilov, 2007-2020www.sview.ru</string>
7
                                <object class="NSFont" key="NSSupport" id="26">
8
                                    <string key="NSName">LucidaGrande</string>
9
                                    <double key="NSSize">11</double>
10
sview-17_04.tar.gz/sview/StMultiApp.cpp -> sview-20_08.tar.gz/sview/StMultiApp.cpp Changed
46
 
1
@@ -17,7 +17,7 @@
2
 static StString getAbout() {
3
     StString anAboutString =
4
         StString("sView ") + StVersionInfo::getSDKVersionString() + '\n'
5
-        + "Copyright (C) 2007-2016 Kirill Gavrilov (kirill@sview.ru).\n"
6
+        + "Copyright (C) 2007-2020 Kirill Gavrilov (kirill@sview.ru).\n"
7
         + "Usage: sView [options] - file\n"
8
         + "Available options:\n"
9
           "  --fullscreen         Open fullscreen\n"
10
@@ -31,6 +31,7 @@
11
           "  --slideshow          Start slideshow\n"
12
           "  --last               Open last file\n"
13
           "  --paused             Open file in paused state\n"
14
+          "  --seek=SECONDS       Seek to specified position\n"
15
           "  --in=image,video     Application to open (predefined values: image, video, diag)\n"
16
           "  --out=RENDERER       Stereoscopic output module (auto, StOutAnaglyph, StOutDual,...)\n"
17
           "  --imageLib=IMGLIB    Setup 3rd-party library for image processing (FFmpeg, FreeImage, DevIL)\n"
18
@@ -54,6 +55,7 @@
19
           "                       mute - mute/unmute audio\n"
20
           "                       vol?VOLUME - specify volume in percents\n"
21
           "                       prev,next - play previous/next item in playlist\n"
22
+          "                       seek?SECONDS - specify volume in percents\n"
23
           "                       fastbwd,fastfwd - seek backward/forward\n"
24
           "                       quit - close the program\n"
25
           "                       current?title - print title of currently played item\n"
26
@@ -110,7 +112,7 @@
27
         } else if(anActLow == "currenttitle") {
28
             anAction = "current?title";
29
         } else if(anAction.isContains('?')) {
30
-            anAction = anAction;
31
+            //anAction = anAction;
32
         } else if(anActLow == "fastbwd") {
33
             anAction = "action?DoSeekLeft";
34
         } else if(anActLow == "fastfwd") {
35
@@ -145,6 +147,10 @@
36
     // select application
37
     const StString ARGUMENT_DRAWER = "in";
38
     StArgument anArgDrawer = anArgs[ARGUMENT_DRAWER];
39
+    if(!anInfo->hasPath() && !anArgDrawer.isValid()) {
40
+        StApplication::readDefaultDrawer(anInfo);
41
+        anArgDrawer = anInfo->getArgumentsMap()[ARGUMENT_DRAWER];
42
+    }
43
     if(anArgDrawer.isValid()) {
44
         if(anArgDrawer.getValue() == "image"
45
         || anArgDrawer.getValue() == "StImageViewer") {
46
sview-17_04.tar.gz/sview/main.ObjC.mm -> sview-20_08.tar.gz/sview/main.ObjC.mm Changed
34
 
1
@@ -181,9 +181,12 @@
2
                 }
3
             }
4
         }
5
-        if(TheOpenInfo->hasPath()
6
-        || anArgsNb > 1) {
7
-            // create StApplication instance only if we know which drawer plugin to launch
8
+
9
+        // create StApplication instance only if we know which drawer plugin to launch
10
+        bool toStart = true;
11
+        //bool toStart = TheOpenInfo->hasPath() || anArgsNb > 1;
12
+        //if(!toStart) { toStart = StApplication::readDefaultDrawer(TheOpenInfo); }
13
+        if(toStart) {
14
             [self launchSelf: NULL];
15
         }
16
         myIsStarted = true;
17
@@ -250,6 +253,16 @@
18
         }
19
 
20
         if(myStApp->closingDown()) {
21
+            StHandle<StOpenInfo> anOther = myStApp->getOpenFileInOtherDrawer();
22
+            if(!anOther.isNull()) {
23
+                myStApp.nullify();
24
+                StHandle<StResourceManager> aResMgr = new StResourceManager();
25
+                myStApp = StMultiApp::getInstance(aResMgr, anOther);
26
+                if(!myStApp.isNull() && myStApp->open()) {
27
+                    return true;
28
+                }
29
+            }
30
+
31
             myStApp.nullify();
32
 
33
             // this will call exit(), so code below has no effect
34
sview-17_04.tar.gz/sview/main.cpp -> sview-20_08.tar.gz/sview/main.cpp Changed
25
 
1
@@ -52,10 +52,20 @@
2
 
3
     StHandle<StResourceManager> aResMgr = new StResourceManager();
4
     StHandle<StApplication>     anApp   = StMultiApp::getInstance(aResMgr);
5
-    if(anApp.isNull() || !anApp->open()) {
6
-        return 1;
7
+    for(;;) {
8
+        if(anApp.isNull() || !anApp->open()) {
9
+            return 1;
10
+        }
11
+
12
+        int aResult = anApp->exec();
13
+        StHandle<StOpenInfo> anOther = anApp->getOpenFileInOtherDrawer();
14
+        if(anOther.isNull()) {
15
+            return aResult;
16
+        }
17
+
18
+        anApp.nullify();
19
+        anApp = StMultiApp::getInstance(aResMgr, anOther);
20
     }
21
-    return anApp->exec();
22
 }
23
 
24
 #endif // __APPLE__
25
sview-20_08.tar.gz/sview/res/drawable-hdpi/ic_media_play.png Added
sview-20_08.tar.gz/sview/res/drawable-mdpi/ic_media_play.png Added
sview-20_08.tar.gz/sview/res/drawable-xhdpi/ic_media_play.png Added
sview-20_08.tar.gz/sview/res/drawable-xxhdpi/ic_media_play.png Added
sview-17_04.tar.gz/sview/res/values/strings.xml -> sview-20_08.tar.gz/sview/res/values/strings.xml Changed
7
 
1
@@ -4,4 +4,5 @@
2
     <string name="app_image_name">sView - Image Viewer</string>
3
     <string name="app_movie_name">sView - Media Player</string>
4
     <string name="app_crash_name">sView - Crash Report</string>
5
+    <string name="app_movie_service_desc">sView - service playing audio in background</string>
6
 </resources>
7
sview-17_04.tar.gz/sview/src/com/sview/StActivity.java -> sview-20_08.tar.gz/sview/src/com/sview/StActivity.java Changed
220
 
1
@@ -146,6 +146,11 @@
2
         myContext = new ContextWrapper(this);
3
         myContext.getExternalFilesDir(null);
4
 
5
+        askUserPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, null);
6
+
7
+        android.os.PowerManager aPowerManager = (android.os.PowerManager)getSystemService(Context.POWER_SERVICE);
8
+        myWakeLock = aPowerManager.newWakeLock(android.os.PowerManager.PARTIAL_WAKE_LOCK, "sView.PartialWakeLock");
9
+
10
         mySensorMgr = (SensorManager )getSystemService(Context.SENSOR_SERVICE);
11
         mySensorOri = mySensorMgr.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
12
         if(mySensorOri == null) {
13
@@ -165,11 +170,64 @@
14
             anInfo.append("Error: native library can not be loaded for security reasons:\n  " + theError.getMessage());
15
             StActivity.exitWithError(this, "Broken apk?\n" + anInfo);
16
         } catch(Exception theError) {
17
-            anInfo.append("Error: unhandled exception:\n  " + theError.getMessage());
18
+            java.io.StringWriter aStringWriter = new java.io.StringWriter();
19
+            theError.printStackTrace (new java.io.PrintWriter (aStringWriter));
20
+            anInfo.append("Error: unhandled exception:\n  " + theError.getMessage()
21
+                        + "\nCall stack:\n" + aStringWriter.toString());
22
             StActivity.exitWithError(this, "Broken apk?\n" + anInfo);
23
         }
24
 
25
         updateHideSystemBars(myToHideStatusBar, myToHideNavBar);
26
+
27
+        // readOpenPath(false) should be called - NULLify intent afterwards
28
+        setIntent(null);
29
+    }
30
+
31
+    /**
32
+     * Request user permission.
33
+     */
34
+    protected void askUserPermission(String thePermission, String theRationale) {
35
+        // Dynamically load methods introduced by API level 23.
36
+        // On older system this permission is granted by user during application installation.
37
+        java.lang.reflect.Method aMetPtrCheckSelfPermission, aMetPtrRequestPermissions, aMetPtrShouldShowRequestPermissionRationale;
38
+        try {
39
+            aMetPtrCheckSelfPermission = myContext.getClass().getMethod("checkSelfPermission", String.class);
40
+            aMetPtrRequestPermissions = getClass().getMethod("requestPermissions", String[].class, int.class);
41
+            aMetPtrShouldShowRequestPermissionRationale = getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
42
+        } catch(SecurityException theError) {
43
+            //postMessage("Unable to find permission methods:\n" + theError.getMessage());
44
+            return;
45
+        } catch(NoSuchMethodException theError) {
46
+            //postMessage("Unable to find permission methods:\n" + theError.getMessage());
47
+            return;
48
+        }
49
+
50
+        try {
51
+            //int isAlreadyGranted = myContext.checkSelfPermission(thePermission);
52
+            int isAlreadyGranted = (Integer )aMetPtrCheckSelfPermission.invoke(myContext, thePermission);
53
+            if(isAlreadyGranted == android.content.pm.PackageManager.PERMISSION_GRANTED) {
54
+                return;
55
+            }
56
+
57
+            //boolean toShowInfo = shouldShowRequestPermissionRationale(thePermission);
58
+            boolean toShowInfo = theRationale != null && (Boolean )aMetPtrShouldShowRequestPermissionRationale.invoke(this, thePermission);
59
+            if(toShowInfo) {
60
+                postMessage(theRationale);
61
+            }
62
+
63
+            // show dialog to user
64
+            //requestPermissions (new String[]{thePermission}, 0);
65
+            aMetPtrRequestPermissions.invoke(this, new String[]{thePermission}, 0);
66
+        } catch(IllegalArgumentException theError) {
67
+            postMessage("Internal error: Unable to call permission method:\n" + theError.getMessage());
68
+            return;
69
+        } catch(IllegalAccessException theError) {
70
+            postMessage("Internal error: Unable to call permission method:\n" + theError.getMessage());
71
+            return;
72
+        } catch(java.lang.reflect.InvocationTargetException theError) {
73
+            postMessage("Internal error: Unable to call permission method:\n" + theError.getMessage());
74
+            return;
75
+        }
76
     }
77
 
78
     /**
79
@@ -222,6 +280,17 @@
80
         }
81
     }
82
 
83
+    /**
84
+     * Redirect key event to C++ level.
85
+     */
86
+    @Override
87
+    public boolean dispatchKeyEvent(android.view.KeyEvent theEvent) {
88
+        if(super.dispatchKeyEvent(theEvent)) {
89
+            return true;
90
+        }
91
+        return myCppGlue != 0 && cppIsKeyOverridden(myCppGlue, theEvent.getKeyCode());
92
+    }
93
+
94
     @Override
95
     public void surfaceCreated(SurfaceHolder theHolder) {
96
         super.surfaceCreated(theHolder);
97
@@ -294,20 +363,61 @@
98
 //region Auxiliary methods
99
 
100
     /**
101
+     * Action to play/pause.
102
+     */
103
+    public static final String THE_ACTION_PLAY_PAUSE = "ACTION_PLAY_PAUSE";
104
+
105
+    /**
106
+     * Action to open previous item in playlist.
107
+     */
108
+    public static final String THE_ACTION_PLAY_PREV = "ACTION_PLAY_PREV";
109
+
110
+    /**
111
+     * Action to open next item in playlist.
112
+     */
113
+    public static final String THE_ACTION_PLAY_NEXT = "ACTION_PLAY_NEXT";
114
+
115
+    /**
116
+     * Set playback action.
117
+     */
118
+    public boolean setPlaybackAction(Intent theIntent) {
119
+        if(myCppGlue == 0 || theIntent == null) {
120
+            return false;
121
+        }
122
+
123
+        if(THE_ACTION_PLAY_PAUSE.equals(theIntent.getAction())) {
124
+            cppSetOpenPath(myCppGlue, THE_ACTION_PLAY_PAUSE, "", false);
125
+            return true;
126
+        } else if(THE_ACTION_PLAY_PREV.equals(theIntent.getAction())) {
127
+            cppSetOpenPath(myCppGlue, THE_ACTION_PLAY_PREV, "", false);
128
+            return true;
129
+        } else if(THE_ACTION_PLAY_NEXT.equals(theIntent.getAction())) {
130
+            cppSetOpenPath(myCppGlue, THE_ACTION_PLAY_NEXT, "", false);
131
+            return true;
132
+        }
133
+        return false;
134
+    }
135
+
136
+    /**
137
      * Read the open path from current intent and nullify it.
138
      * This method is called by StAndroidGlue from C++.
139
      */
140
-    protected void readOpenPath() {
141
+    protected void readOpenPath(boolean theToNullifyIntent) {
142
         if(myCppGlue == 0) {
143
             return;
144
         }
145
 
146
         Intent anIntent = getIntent();
147
-        setIntent(null);
148
+        if(theToNullifyIntent) {
149
+            setIntent(null);
150
+        }
151
         if(anIntent == null) {
152
             cppSetOpenPath(myCppGlue, "", "", false);
153
             return;
154
         }
155
+        if(setPlaybackAction(anIntent)) {
156
+            return;
157
+        }
158
 
159
         String anOpenPath = anIntent.getDataString();
160
         String anOpenMime = anIntent.getType();
161
@@ -443,6 +553,36 @@
162
     }
163
 
164
     /**
165
+     * Set new activity title.
166
+     */
167
+    public void setWindowTitle(String theTitle) {
168
+        if(android.os.Build.VERSION.SDK_INT < 21) {
169
+            return;
170
+        }
171
+
172
+        final String aTitle = theTitle;
173
+        this.runOnUiThread (new Runnable() { public void run() {
174
+            //setTitle(aTitle); // sets window title, which we don't have...
175
+            setTaskDescription(new android.app.ActivityManager.TaskDescription(aTitle));
176
+        }});
177
+    }
178
+
179
+    /**
180
+     * Keep CPU on.
181
+     */
182
+    public void setPartialWakeLockOn(String theTitle, boolean theToLock) {
183
+        if(myWakeLock == null) {
184
+            return;
185
+        }
186
+
187
+        if(theToLock) {
188
+            myWakeLock.acquire();
189
+        } else if(myWakeLock.isHeld()) {
190
+            myWakeLock.release();
191
+        }
192
+    }
193
+
194
+    /**
195
      * Method to turn stereo output on or off.
196
      */
197
     public void setHardwareStereoOn(boolean theToEnable) {
198
@@ -598,6 +738,12 @@
199
     private native void cppSetSwapEyes(long theCppPtr,
200
                                        boolean theToSwap);
201
 
202
+    /**
203
+     * Return TRUE if key is processed by application.
204
+     */
205
+    private native boolean cppIsKeyOverridden(long theCppPtr,
206
+                                              int theKeyCode);
207
+
208
 //endregion
209
 
210
     @SuppressWarnings("deprecation")
211
@@ -606,6 +752,8 @@
212
 //region class fields
213
 
214
     protected ContextWrapper myContext;
215
+    protected android.os.PowerManager.WakeLock myWakeLock;
216
+
217
     protected SensorManager  mySensorMgr;
218
     protected Sensor         mySensorOri;
219
     protected float          myQuat[] = { 0.0f, 0.0f, 0.0f, 1.0f };
220
sview-17_04.tar.gz/sview/src/com/sview/StMovieActivity.java -> sview-20_08.tar.gz/sview/src/com/sview/StMovieActivity.java Changed
71
 
1
@@ -13,6 +13,11 @@
2
 public class StMovieActivity extends StActivity {
3
 
4
     /**
5
+     * Global reference to activity for managing by background service.
6
+     */
7
+    public static StMovieActivity backgroundActivity;
8
+
9
+    /**
10
      * Virtual method defining StApplication class.
11
      */
12
     @Override
13
@@ -21,6 +26,13 @@
14
     }
15
 
16
     /**
17
+     * Return current title.
18
+     */
19
+    public String getCurrentTitle() {
20
+        return myCurrentTitle;
21
+    }
22
+
23
+    /**
24
      * Create activity.
25
      */
26
     @Override
27
@@ -28,4 +40,43 @@
28
         super.onCreate(theSavedInstanceState);
29
     }
30
 
31
+    /**
32
+     * Keep CPU on.
33
+     */
34
+    @Override
35
+    public void setPartialWakeLockOn(String theTitle, boolean theToLock) {
36
+        if(myWakeLock == null) {
37
+            return;
38
+        }
39
+
40
+        super.setPartialWakeLockOn(theTitle, theToLock);
41
+        if(android.os.Build.VERSION.SDK_INT < 24) {
42
+            return;
43
+        }
44
+
45
+        final String  aTitle = theTitle;
46
+        final boolean toLock = theToLock;
47
+        final StMovieActivity aThis = this;
48
+        this.runOnUiThread(new Runnable() { public void run() {
49
+            // start a dummy foreground service, which actually does nothing but shows a system notification;
50
+            // this service (but the very existance) prevents system closing/suspending sView working threads playing audio in background
51
+            myCurrentTitle = aTitle;
52
+            android.content.Intent anIntent = new android.content.Intent(aThis, StMovieService.class);
53
+            if(toLock) {
54
+                backgroundActivity = aThis;
55
+                anIntent.setAction(toLock ? StMovieService.THE_ACTION_START_SERVICE : StMovieService.THE_ACTION_STOP_SERVICE);
56
+                if(android.os.Build.VERSION.SDK_INT >= 26) {
57
+                    startForegroundService(anIntent);
58
+                } else {
59
+                    startService(anIntent);
60
+                }
61
+            } else {
62
+                backgroundActivity = null;
63
+                stopService(anIntent);
64
+            }
65
+        }});
66
+    }
67
+
68
+    private String myCurrentTitle;
69
+
70
 }
71
sview-20_08.tar.gz/sview/src/com/sview/StMovieService.java Added
192
 
1
@@ -0,0 +1,190 @@
2
+/**
3
+ * This is source code for sView
4
+ *
5
+ * Copyright © Kirill Gavrilov, 2019
6
+ */
7
+package com.sview;
8
+
9
+import android.os.Bundle;
10
+
11
+/**
12
+ * Dummy foreground service for playing audio in background.
13
+ * Does nothing but shows a notification.
14
+ */
15
+public class StMovieService extends android.app.Service  {
16
+
17
+    /**
18
+     * Action to start service.
19
+     */
20
+    public static final String THE_ACTION_START_SERVICE = "ACTION_START_SERVICE";
21
+
22
+    /**
23
+     * Action to stop service.
24
+     */
25
+    public static final String THE_ACTION_STOP_SERVICE = "ACTION_STOP_SERVICE";
26
+
27
+    /**
28
+     * Custom channel ID.
29
+     */
30
+    private final String THE_SVIEW_AUDIO_CHANNEL_ID = "com.sview.audio_channel";
31
+
32
+    /**
33
+     * Empty constructor.
34
+     */
35
+    public StMovieService() {
36
+        //
37
+    }
38
+
39
+    /**
40
+     * Create service.
41
+     */
42
+    @Override
43
+    public void onCreate() {
44
+        super.onCreate();
45
+        createNotificationChannel();
46
+        // should be started within several seconds, or will be killed by system
47
+        startForegroundService();
48
+    }
49
+
50
+    /**
51
+     * Destroy service.
52
+     */
53
+    @Override
54
+    public void onDestroy() {
55
+        //
56
+    }
57
+
58
+    /**
59
+     * Create binding.
60
+     */
61
+    @Override
62
+    public android.os.IBinder onBind(android.content.Intent theIntent) {
63
+        // we don't provide binding, so return null
64
+        return null;
65
+    }
66
+
67
+    /**
68
+     * Start a command.
69
+     */
70
+    @Override
71
+    public int onStartCommand(android.content.Intent theIntent, int theFlags, int theStartId) {
72
+        String anAction = theIntent != null ? theIntent.getAction() : THE_ACTION_STOP_SERVICE;
73
+        //android.widget.Toast.makeText(this, " @@ " + anAction, android.widget.Toast.LENGTH_LONG).show();
74
+        switch(anAction) {
75
+            case THE_ACTION_START_SERVICE: {
76
+                // if we get killed, after returning from here, restart
77
+                startForegroundService();
78
+                return START_STICKY;
79
+            }
80
+            case THE_ACTION_STOP_SERVICE: {
81
+                stopForegroundService();
82
+                return START_NOT_STICKY;
83
+            }
84
+            case StActivity.THE_ACTION_PLAY_PREV:
85
+            case StActivity.THE_ACTION_PLAY_NEXT:
86
+            case StActivity.THE_ACTION_PLAY_PAUSE: {
87
+                //android.widget.Toast.makeText(this, " $$ " + anAction, android.widget.Toast.LENGTH_LONG).show();
88
+                final StMovieActivity aMainActivity = StMovieActivity.backgroundActivity;
89
+                if(aMainActivity != null) {
90
+                    aMainActivity.setPlaybackAction(theIntent);
91
+                }
92
+                return START_NOT_STICKY;
93
+            }
94
+        }
95
+        return START_NOT_STICKY;
96
+    }
97
+
98
+    /**
99
+     * Start foreground service - create notification.
100
+     */
101
+    private void startForegroundService() {
102
+        final StMovieActivity aMainActivity = StMovieActivity.backgroundActivity;
103
+        String anActiveItem = "Audio playback";
104
+        if(aMainActivity != null) {
105
+            anActiveItem = aMainActivity.getCurrentTitle();
106
+        }
107
+
108
+        android.content.Intent anIntent = new android.content.Intent(this, StMovieActivity.class);
109
+        android.app.PendingIntent aPendingIntent = android.app.PendingIntent.getActivity(this, 0, anIntent, 0);
110
+
111
+        android.app.Notification.Builder aNoti;
112
+        if(android.os.Build.VERSION.SDK_INT >= 26) {
113
+            aNoti = new android.app.Notification.Builder(this, THE_SVIEW_AUDIO_CHANNEL_ID);
114
+        } else {
115
+            aNoti = new android.app.Notification.Builder(this);
116
+        }
117
+        aNoti.setPriority(android.app.Notification.PRIORITY_LOW); // Android 8.0+ will use Notification Channel importance instead
118
+        //aNoti.setAutoCancel(true);
119
+        aNoti.setContentIntent(aPendingIntent); // intent on tapping notification
120
+        aNoti.setContentTitle(anActiveItem);
121
+        //aNoti.setContentText("");
122
+        aNoti.setSmallIcon(com.sview.R.drawable.ic_media_play);
123
+        //aNoti.setLargeIcon(aBitmap);
124
+
125
+        // add buttons (note that Android 7.0+ will NOT show action icons!)
126
+        {
127
+            android.content.Intent aPlayIntent = new android.content.Intent(this, StMovieService.class);
128
+            aPlayIntent.setAction(StActivity.THE_ACTION_PLAY_PREV);
129
+            android.app.PendingIntent aPendingPlayIntent = android.app.PendingIntent.getService(this, 0, aPlayIntent, 0);
130
+            aNoti.addAction(new android.app.Notification.Action(android.R.drawable.ic_media_previous,
131
+                                                                android.os.Build.VERSION.SDK_INT >= 24
132
+                                                              ? "    \u23EE    "
133
+                                                              : "PREV",
134
+                                                                aPendingPlayIntent));
135
+        }
136
+        {
137
+            android.content.Intent aPlayIntent = new android.content.Intent(this, StMovieService.class);
138
+            aPlayIntent.setAction(StActivity.THE_ACTION_PLAY_PAUSE);
139
+            android.app.PendingIntent aPendingPlayIntent = android.app.PendingIntent.getService(this, 0, aPlayIntent, 0);
140
+            aNoti.addAction(new android.app.Notification.Action(android.R.drawable.ic_media_pause,
141
+                                                                android.os.Build.VERSION.SDK_INT >= 24
142
+                                                              ? "    \u23F9    " // "    \u23F8    "
143
+                                                              : "PAUSE", aPendingPlayIntent));
144
+        }
145
+        {
146
+            android.content.Intent aPlayIntent = new android.content.Intent(this, StMovieService.class);
147
+            aPlayIntent.setAction(StActivity.THE_ACTION_PLAY_NEXT);
148
+            android.app.PendingIntent aPendingPlayIntent = android.app.PendingIntent.getService(this, 0, aPlayIntent, 0);
149
+            aNoti.addAction(new android.app.Notification.Action(android.R.drawable.ic_media_next,
150
+                                                                android.os.Build.VERSION.SDK_INT >= 24
151
+                                                              ? "    \u23ED    "
152
+                                                              : "NEXT",
153
+                                                                aPendingPlayIntent));
154
+        }
155
+        final int aNotifId = 1; // unique ID, should not be 0
156
+        try {
157
+            startForeground(aNotifId, aNoti.build());
158
+        } catch(SecurityException theError) {
159
+            android.widget.Toast.makeText(this,
160
+                                          "Internal error: unable to start StMovieService.startForeground() due to security reasons:\n  " + theError.getMessage(),
161
+                                          android.widget.Toast.LENGTH_LONG).show();
162
+        }
163
+    }
164
+
165
+    /**
166
+     * Stop foreground service and remove the notification.
167
+     */
168
+    private void stopForegroundService() {
169
+        stopForeground(true);
170
+        stopSelf();
171
+    }
172
+
173
+    /**
174
+     * Create the NotificationChannel (adjust settings of the channel).
175
+     */
176
+    private void createNotificationChannel() {
177
+        if(android.os.Build.VERSION.SDK_INT < 26) {
178
+            return;
179
+        }
180
+
181
+        android.app.NotificationChannel aChannel = new android.app.NotificationChannel(THE_SVIEW_AUDIO_CHANNEL_ID,
182
+                                                                                       THE_SVIEW_AUDIO_CHANNEL_ID,
183
+                                                                                       android.app.NotificationManager.IMPORTANCE_LOW);
184
+        aChannel.enableLights(false);
185
+        aChannel.enableVibration(false);
186
+        aChannel.setSound(null, null);
187
+        android.app.NotificationManager aNotifMgr = getSystemService(android.app.NotificationManager.class);
188
+        aNotifMgr.createNotificationChannel(aChannel);
189
+    }
190
+
191
+}
192
sview-17_04.tar.gz/sview/sview.cbp -> sview-20_08.tar.gz/sview/sview.cbp Changed
32
 
1
@@ -249,6 +249,30 @@
2
        <Unit filename="Resources/English.lproj/MainMenu.xib" />
3
        <Unit filename="Resources/sView.icns" />
4
        <Unit filename="Resources/sView_Media.icns" />
5
+       <Unit filename="src/com/sview/CrashReportActivity.java">
6
+           <Option compile="0" />
7
+           <Option link="0" />
8
+       </Unit>
9
+       <Unit filename="src/com/sview/MainActivity.java">
10
+           <Option compile="0" />
11
+           <Option link="0" />
12
+       </Unit>
13
+       <Unit filename="src/com/sview/StActivity.java">
14
+           <Option compile="0" />
15
+           <Option link="0" />
16
+       </Unit>
17
+       <Unit filename="src/com/sview/StImageActivity.java">
18
+           <Option compile="0" />
19
+           <Option link="0" />
20
+       </Unit>
21
+       <Unit filename="src/com/sview/StMovieActivity.java">
22
+           <Option compile="0" />
23
+           <Option link="0" />
24
+       </Unit>
25
+       <Unit filename="src/com/sview/StS3dvSurface.java">
26
+           <Option compile="0" />
27
+           <Option link="0" />
28
+       </Unit>
29
        <Unit filename="StAppResponder.h">
30
            <Option target="MAC_gcc" />
31
            <Option target="MAC_gcc_DEBUG" />
32
sview-17_04.tar.gz/sview/sview.rc -> sview-20_08.tar.gz/sview/sview.rc Changed
10
 
1
@@ -16,7 +16,7 @@
2
     BEGIN
3
       VALUE "FileDescription", "sView\000"
4
       VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
5
-      VALUE "LegalCopyright", "\251 2007-2017 Kirill Gavrilov\000"
6
+      VALUE "LegalCopyright", "\251 2007-2020 Kirill Gavrilov and sView developers\000"
7
       VALUE "ProductName", "sView\000"
8
       VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
9
       VALUE "OfficialSite", "www.sview.ru\000"
10