:Merge remote-tracking branch 'upstream/master' into master-windows-changes

This commit is contained in:
LAGonauta 2022-06-05 11:12:23 -03:00
commit c29032bcc6
28 changed files with 392 additions and 107 deletions

View file

@ -206,7 +206,11 @@ include(${VALA_USE_FILE})
include(MultiFind)
include(GlibCompileResourcesSupport)
set(CMAKE_VALA_FLAGS "${CMAKE_VALA_FLAGS} --target-glib=${GLib_GLOBAL_VERSION}")
find_package(GLib ${GLib_GLOBAL_VERSION} REQUIRED)
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" GLib_MAJOR_VERSION "${GLib_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" GLib_MINOR_VERSION "${GLib_VERSION}")
math(EXPR GLib_LAST_RELEASE_MINOR_VERSION "${GLib_MINOR_VERSION} / 2 * 2")
set(CMAKE_VALA_FLAGS "${CMAKE_VALA_FLAGS} --target-glib=${GLib_MAJOR_VERSION}.${GLib_LAST_RELEASE_MINOR_VERSION}")
add_subdirectory(qlite)
add_subdirectory(xmpp-vala)

View file

@ -1,31 +0,0 @@
include(PkgConfigWithFallback)
find_pkg_config_with_fallback(Soup
PKG_CONFIG_NAME libsoup-2.4
LIB_NAMES soup-2.4
INCLUDE_NAMES libsoup/soup.h
INCLUDE_DIR_SUFFIXES libsoup-2.4 libsoup-2.4/include libsoup libsoup/include
DEPENDS GIO
)
if(Soup_FOUND AND NOT Soup_VERSION)
find_file(Soup_VERSION_HEADER "libsoup/soup-version.h" HINTS ${Soup_INCLUDE_DIRS})
mark_as_advanced(Soup_VERSION_HEADER)
if(Soup_VERSION_HEADER)
file(STRINGS "${Soup_VERSION_HEADER}" Soup_MAJOR_VERSION REGEX "^#define SOUP_MAJOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MAJOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MAJOR_VERSION "${Soup_MAJOR_VERSION}")
file(STRINGS "${Soup_VERSION_HEADER}" Soup_MINOR_VERSION REGEX "^#define SOUP_MINOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MINOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MINOR_VERSION "${Soup_MINOR_VERSION}")
file(STRINGS "${Soup_VERSION_HEADER}" Soup_MICRO_VERSION REGEX "^#define SOUP_MICRO_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MICRO_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MICRO_VERSION "${Soup_MICRO_VERSION}")
set(Soup_VERSION "${Soup_MAJOR_VERSION}.${Soup_MINOR_VERSION}.${Soup_MICRO_VERSION}")
unset(Soup_MAJOR_VERSION)
unset(Soup_MINOR_VERSION)
unset(Soup_MICRO_VERSION)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Soup
REQUIRED_VARS Soup_LIBRARY
VERSION_VAR Soup_VERSION)

31
cmake/FindSoup2.cmake Normal file
View file

@ -0,0 +1,31 @@
include(PkgConfigWithFallback)
find_pkg_config_with_fallback(Soup2
PKG_CONFIG_NAME libsoup-2.4
LIB_NAMES soup-2.4
INCLUDE_NAMES libsoup/soup.h
INCLUDE_DIR_SUFFIXES libsoup-2.4 libsoup-2.4/include libsoup libsoup/include
DEPENDS GIO
)
if(Soup2_FOUND AND NOT Soup2_VERSION)
find_file(Soup2_VERSION_HEADER "libsoup/soup-version.h" HINTS ${Soup_INCLUDE_DIRS})
mark_as_advanced(Soup2_VERSION_HEADER)
if(Soup_VERSION_HEADER)
file(STRINGS "${Soup2_VERSION_HEADER}" Soup2_MAJOR_VERSION REGEX "^#define SOUP_MAJOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MAJOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MAJOR_VERSION "${Soup2_MAJOR_VERSION}")
file(STRINGS "${Soup2_VERSION_HEADER}" Soup2_MINOR_VERSION REGEX "^#define SOUP_MINOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MINOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MINOR_VERSION "${Soup2_MINOR_VERSION}")
file(STRINGS "${Soup2_VERSION_HEADER}" Soup2_MICRO_VERSION REGEX "^#define SOUP_MICRO_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MICRO_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup_MICRO_VERSION "${Soup2_MICRO_VERSION}")
set(Soup_VERSION "${Soup2_MAJOR_VERSION}.${Soup2_MINOR_VERSION}.${Soup2_MICRO_VERSION}")
unset(Soup2_MAJOR_VERSION)
unset(Soup2_MINOR_VERSION)
unset(Soup2_MICRO_VERSION)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Soup2
REQUIRED_VARS Soup2_LIBRARY
VERSION_VAR Soup2_VERSION)

31
cmake/FindSoup3.cmake Normal file
View file

@ -0,0 +1,31 @@
include(PkgConfigWithFallback)
find_pkg_config_with_fallback(Soup3
PKG_CONFIG_NAME libsoup-3.0
LIB_NAMES soup-3.0
INCLUDE_NAMES libsoup/soup.h
INCLUDE_DIR_SUFFIXES libsoup-2.4 libsoup-2.4/include libsoup libsoup/include
DEPENDS GIO
)
if(Soup3_FOUND AND NOT Soup3_VERSION)
find_file(Soup3_VERSION_HEADER "libsoup/soup-version.h" HINTS ${Soup3_INCLUDE_DIRS})
mark_as_advanced(Soup3_VERSION_HEADER)
if(Soup3_VERSION_HEADER)
file(STRINGS "${Soup3_VERSION_HEADER}" Soup3_MAJOR_VERSION REGEX "^#define SOUP_MAJOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MAJOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup3_MAJOR_VERSION "${Soup3_MAJOR_VERSION}")
file(STRINGS "${Soup3_VERSION_HEADER}" Soup3_MINOR_VERSION REGEX "^#define SOUP_MINOR_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MINOR_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup3_MINOR_VERSION "${Soup3_MINOR_VERSION}")
file(STRINGS "${Soup3_VERSION_HEADER}" Soup3_MICRO_VERSION REGEX "^#define SOUP_MICRO_VERSION +\\(?([0-9]+)\\)?$")
string(REGEX REPLACE "^#define SOUP_MICRO_VERSION \\(?([0-9]+)\\)?$" "\\1" Soup3_MICRO_VERSION "${Soup3_MICRO_VERSION}")
set(Soup3_VERSION "${Soup3_MAJOR_VERSION}.${Soup3_MINOR_VERSION}.${Soup3_MICRO_VERSION}")
unset(Soup3_MAJOR_VERSION)
unset(Soup3_MINOR_VERSION)
unset(Soup3_MICRO_VERSION)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Soup3
REQUIRED_VARS Soup3_LIBRARY
VERSION_VAR Soup3_VERSION)

View file

@ -250,11 +250,15 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0047.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:note>For use with XEP-0261</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
<xmpp:status>deprecated</xmpp:status>
<xmpp:note>Migrating to XEP-0402 if supported by server</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -273,6 +277,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0059.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>For use with XEP-0313</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -284,6 +290,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0065.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>For use with XEP-0260</xmpp:note>
</xmpp:SupportedXep>
</implements>
@ -291,6 +298,7 @@
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0066.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:note>For file transfers using XEP-0363</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -326,27 +334,32 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0153.html"/>
<xmpp:status>deprecated</xmpp:status>
<xmpp:note>Only to fetch Avatars from other users</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0166.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0167.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0176.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -358,7 +371,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0191.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -382,21 +395,25 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0215.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0222.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0223.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0234.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -409,11 +426,14 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>No support for sending</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0260.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -431,21 +451,26 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0293.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0294.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0297.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:note>For use with XEP-0280</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>1.2.0</xmpp:version>
<xmpp:since>0.2</xmpp:since>
</xmpp:SupportedXep>
@ -460,6 +485,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0320.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>1.0.0</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
@ -471,16 +498,20 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0334.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0353.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.3.1</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -506,11 +537,13 @@
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.3.0</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0391.html"/>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -522,6 +555,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0396.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -533,16 +567,20 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0402.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0410.html"/>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>No support for embedded thumbnails</xmpp:note>
</xmpp:SupportedXep>
</implements>
</Project>

View file

@ -70,11 +70,15 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0047.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:note>For use with XEP-0261</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html" />
<xmpp:status>deprecated</xmpp:status>
<xmpp:note>Migrating to XEP-0402 if supported by server</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -93,6 +97,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0059.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:note>For use with XEP-0313</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -104,6 +110,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0065.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:note>For use with XEP-0260</xmpp:note>
</xmpp:SupportedXep>
</implements>
@ -111,6 +118,7 @@
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0066.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:note>For file transfers using XEP-0363</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
@ -146,27 +154,32 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0153.html" />
<xmpp:status>deprecated</xmpp:status>
<xmpp:note>Only to fetch Avatars from other users</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0166.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0167.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0176.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -178,7 +191,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0191.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -202,21 +215,25 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0215.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0222.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0223.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0234.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -229,11 +246,14 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:note>No support for sending</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0260.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -251,21 +271,26 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0293.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0294.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0297.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:note>For use with XEP-0280</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:version>1.2.0</xmpp:version>
<xmpp:since>0.2</xmpp:since>
</xmpp:SupportedXep>
@ -280,6 +305,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0320.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:version>1.0.0</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
@ -291,16 +318,20 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0334.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0353.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.3.1</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -326,11 +357,13 @@
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html" />
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.3.0</xmpp:version>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0391.html" />
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -342,6 +375,7 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0396.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
@ -353,16 +387,20 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0402.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0410.html" />
<xmpp:status>complete</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html" />
<xmpp:status>partial</xmpp:status>
<xmpp:note>No support for embedded thumbnails</xmpp:note>
</xmpp:SupportedXep>
</implements>
</Project>

View file

@ -89,7 +89,7 @@ DEPENDS
${CMAKE_BINARY_DIR}/exports/dino_i18n.h
)
add_definitions(${VALA_CFLAGS} -DDINO_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}" -DG_LOG_DOMAIN="libdino")
add_definitions(${VALA_CFLAGS} -DDINO_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}" -DG_LOG_DOMAIN="libdino" -DDINO_VERSION=\"${PROJECT_VERSION}\")
add_library(libdino SHARED ${LIBDINO_VALA_C} ${CMAKE_BINARY_DIR}/exports/dino_i18n.h)
add_dependencies(libdino dino-vapi)
target_link_libraries(libdino xmpp-vala qlite ${LIBDINO_PACKAGES} m)

View file

@ -1,7 +1,13 @@
using Dino.Entities;
namespace Dino {
extern const string VERSION;
public string get_version() { return VERSION; }
public string get_short_version() {
if (!VERSION.contains("~")) return VERSION;
return VERSION.split("~")[0] + "+";
}
public interface Application : GLib.Application {

View file

@ -70,6 +70,7 @@ public class FileTransfer : Object {
public State state { get; set; default=State.NOT_STARTED; }
public int provider { get; set; }
public string info { get; set; }
public Cancellable cancellable { get; default=new Cancellable(); }
private Database? db;
private string storage_dir;

View file

@ -246,7 +246,7 @@ public class FileManager : StreamInteractionModule, Object {
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
yield os.splice_async(input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE|OutputStreamSpliceFlags.CLOSE_TARGET);
yield os.splice_async(input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE | OutputStreamSpliceFlags.CLOSE_TARGET, Priority.LOW, file_transfer.cancellable);
file_transfer.path = file.get_basename();
file_transfer.input_stream = yield file.read_async();
@ -299,14 +299,15 @@ public class FileManager : StreamInteractionModule, Object {
if (is_sender_trustworthy(file_transfer, conversation)) {
try {
yield get_file_meta(file_provider, file_transfer, conversation, receive_data);
if (file_transfer.size >= 0 && file_transfer.size < 5000000) {
yield download_file_internal(file_provider, file_transfer, conversation);
}
} catch (Error e) {
warning("Error downloading file: %s", e.message);
file_transfer.state = FileTransfer.State.FAILED;
}
if (file_transfer.size >= 0 && file_transfer.size < 5000000) {
download_file_internal.begin(file_provider, file_transfer, conversation, (_, res) => {
download_file_internal.end(res);
});
}
}
conversation.last_active = file_transfer.time;

View file

@ -48,7 +48,7 @@ public abstract class Gee.TestCase : Object {
}
public GLib.TestSuite get_suite () {
return this.suite;
return (owned) this.suite;
}
private class Adaptor {

View file

@ -218,7 +218,7 @@ else()
set(DINO_NUMERIC_VERSION "0,0,0,0")
endif ()
add_definitions(${VALA_CFLAGS} -DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\" -DLOCALE_INSTALL_DIR=\"${LOCALE_INSTALL_DIR}\" -DDINO_VERSION=\"${PROJECT_VERSION}\" -DDINO_NUMERIC_VERSION=${DINO_NUMERIC_VERSION})
add_definitions(${VALA_CFLAGS} -DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\" -DLOCALE_INSTALL_DIR=\"${LOCALE_INSTALL_DIR}\" -DDINO_NUMERIC_VERSION=${DINO_NUMERIC_VERSION})
if(WIN32)
add_link_options("-Wl,--export-all-symbols")
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> --use-temp-file -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")

View file

@ -370,3 +370,7 @@ box.dino-input-error label.input-status-highlight-once {
.dino-call-window .own-video {
box-shadow: 0 0 2px 0 rgba(0,0,0,0.5);
}
.qrcode-container {
background: white; /* Color of the quiet zone. MUST have the same "reflectance" as light modules of the QR code. */
}

View file

@ -42,7 +42,7 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
startup.connect(() => {
if (print_version) {
print(@"Dino $(Dino.VERSION)\n");
print(@"Dino $(Dino.get_version())\n");
Process.exit(0);
}
@ -270,7 +270,7 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
}
private void show_about_window() {
string? version = Dino.VERSION.strip().length == 0 ? null : Dino.VERSION;
string? version = Dino.get_version().strip().length == 0 ? null : Dino.get_version();
if (version != null && !version.contains("git")) {
switch (version.substring(0, 3)) {
case "0.2": version = @"$version - <span font_style='italic'>Mexican Caribbean Coral Reefs</span>"; break;

View file

@ -22,6 +22,7 @@ public class Dino.Ui.CallWindowController : Object {
private bool window_size_changed = false;
private ulong[] call_window_handler_ids = new ulong[0];
private ulong[] bottom_bar_handler_ids = new ulong[0];
private uint inhibit_cookie;
public CallWindowController(CallWindow call_window, CallState call_state, StreamInteractor stream_interactor) {
this.call_window = call_window;
@ -118,6 +119,19 @@ public class Dino.Ui.CallWindowController : Object {
update_audio_device_choices();
update_video_device_choices();
var app = GLib.Application.get_default() as Application;
inhibit_cookie = app.inhibit(call_window, IDLE | SUSPEND, "Ongoing call");
if (inhibit_cookie == 0) {
warning("suspend inhibit request failed or unsupported");
}
call_window.destroy.connect(() => {
if (inhibit_cookie != 0) {
app.uninhibit(inhibit_cookie);
}
});
}
private void invite_button_clicked() {

View file

@ -19,6 +19,7 @@ public class FileDefaultWidget : EventBox {
public ModelButton file_open_button;
public ModelButton file_save_button;
public ModelButton cancel_button;
private FileTransfer.State state;
@ -27,6 +28,7 @@ public class FileDefaultWidget : EventBox {
this.leave_notify_event.connect(on_pointer_left_event);
file_open_button = new ModelButton() { text=_("Open"), visible=true };
file_save_button = new ModelButton() { text=_("Save as…"), visible=true };
cancel_button = new ModelButton() { text=_("Cancel"), visible=true };
}
public void update_file_info(string? mime_type, FileTransfer.State state, long size) {
@ -59,6 +61,18 @@ public class FileDefaultWidget : EventBox {
mime_label.label = _("Downloading %s…").printf(get_size_string(size));
spinner.active = true;
image_stack.set_visible_child_name("spinner");
// Create a menu
Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu();
Box file_menu_box = new Box(Orientation.VERTICAL, 0) { margin=10, visible=true };
file_menu_box.add(cancel_button);
popover_menu.add(file_menu_box);
file_menu.popover = popover_menu;
file_menu.button_release_event.connect(() => {
popover_menu.visible = true;
return true;
});
popover_menu.closed.connect(on_pointer_left);
break;
case FileTransfer.State.NOT_STARTED:
if (mime_description != null) {
@ -84,7 +98,7 @@ public class FileDefaultWidget : EventBox {
if (state == FileTransfer.State.NOT_STARTED) {
image_stack.set_visible_child_name("download_image");
}
if (state == FileTransfer.State.COMPLETE) {
if (state == FileTransfer.State.COMPLETE || state == FileTransfer.State.IN_PROGRESS) {
file_menu.opacity = 1;
}
return false;

View file

@ -131,6 +131,7 @@ public class FileDefaultWidgetController : Object {
widget.button_release_event.connect(on_clicked);
widget.file_open_button.clicked.connect(open_file);
widget.file_save_button.clicked.connect(save_file);
widget.cancel_button.clicked.connect(cancel_download);
}
public void set_file_transfer(FileTransfer file_transfer, StreamInteractor stream_interactor) {
@ -186,6 +187,10 @@ public class FileDefaultWidgetController : Object {
}
}
private void cancel_download() {
file_transfer.cancellable.cancel();
}
private bool on_clicked(EventButton event_button) {
switch (state) {
case FileTransfer.State.COMPLETE:

View file

@ -1,10 +1,18 @@
set(HTTP_FILES_DEFINITIONS)
if(USE_SOUP3)
set(Soup Soup3)
set(HTTP_FILES_DEFINITIONS ${HTTP_FILES_DEFINITIONS} SOUP_3)
else()
set(Soup Soup2)
endif()
find_packages(HTTP_FILES_PACKAGES REQUIRED
Gee
GLib
GModule
GObject
GTK3
Soup
${Soup}
)
vala_precompile(HTTP_FILES_VALA_C
@ -19,6 +27,8 @@ CUSTOM_VAPIS
${CMAKE_BINARY_DIR}/exports/qlite.vapi
PACKAGES
${HTTP_FILES_PACKAGES}
DEFINITIONS
${HTTP_FILES_DEFINITIONS}
)
add_definitions(${VALA_CFLAGS})

View file

@ -46,6 +46,38 @@ public class FileProvider : Dino.FileProvider, Object {
}
}
private class LimitInputStream : InputStream {
InputStream inner;
int64 remaining_size;
public LimitInputStream(InputStream inner, int64 max_size) {
this.inner = inner;
this.remaining_size = max_size;
}
private ssize_t check_limit(ssize_t read) throws IOError {
this.remaining_size -= read;
if (remaining_size < 0) throw new IOError.FAILED("Stream length exceeded limit");
return read;
}
public override ssize_t read(uint8[] buffer, Cancellable? cancellable = null) throws IOError {
return check_limit(inner.read(buffer, cancellable));
}
public override async ssize_t read_async(uint8[]? buffer, int io_priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws IOError {
return check_limit(yield inner.read_async(buffer, io_priority, cancellable));
}
public override bool close(Cancellable? cancellable = null) throws IOError {
return inner.close(cancellable);
}
public override async bool close_async(int io_priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws IOError {
return yield inner.close_async(io_priority, cancellable);
}
}
private void on_file_message(Entities.Message message, Conversation conversation) {
var additional_info = message.id.to_string();
@ -64,24 +96,28 @@ public class FileProvider : Dino.FileProvider, Object {
if (http_receive_data == null) return file_meta;
var session = new Soup.Session();
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
var head_message = new Soup.Message("HEAD", http_receive_data.url);
head_message.request_headers.append("Accept-Encoding", "identity");
if (head_message != null) {
try {
yield session.send_async(head_message, null);
} catch (Error e) {
throw new FileReceiveError.GET_METADATA_FAILED("HEAD request failed");
}
try {
#if SOUP_3
yield session.send_async(head_message, GLib.Priority.LOW, null);
#else
yield session.send_async(head_message, null);
#endif
} catch (Error e) {
throw new FileReceiveError.GET_METADATA_FAILED("HEAD request failed");
}
string? content_type = null, content_length = null;
head_message.response_headers.foreach((name, val) => {
if (name == "Content-Type") content_type = val;
if (name == "Content-Length") content_length = val;
});
file_meta.mime_type = content_type;
if (content_length != null) {
file_meta.size = int.parse(content_length);
}
string? content_type = null, content_length = null;
head_message.response_headers.foreach((name, val) => {
if (name.down() == "content-type") content_type = val;
if (name.down() == "content-length") content_length = val;
});
file_meta.mime_type = content_type;
if (content_length != null) {
file_meta.size = int64.parse(content_length);
}
return file_meta;
@ -95,11 +131,21 @@ public class FileProvider : Dino.FileProvider, Object {
HttpFileReceiveData? http_receive_data = receive_data as HttpFileReceiveData;
if (http_receive_data == null) assert(false);
try {
var session = new Soup.Session();
Soup.Request request = session.request(http_receive_data.url);
var session = new Soup.Session();
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
var get_message = new Soup.Message("GET", http_receive_data.url);
return yield request.send_async(null);
try {
#if SOUP_3
InputStream stream = yield session.send_async(get_message, GLib.Priority.LOW, file_transfer.cancellable);
#else
InputStream stream = yield session.send_async(get_message, file_transfer.cancellable);
#endif
if (file_meta.size != -1) {
return new LimitInputStream(stream, file_meta.size);
} else {
return stream;
}
} catch (Error e) {
throw new FileReceiveError.DOWNLOAD_FAILED("Downloading file error: %s".printf(e.message));
}

View file

@ -73,6 +73,7 @@ public class HttpFileSender : FileSender, Object {
}
}
#if !SOUP_3
private static void transfer_more_bytes(InputStream stream, Soup.MessageBody body) {
uint8[] bytes = new uint8[4096];
ssize_t read = stream.read(bytes);
@ -83,25 +84,35 @@ public class HttpFileSender : FileSender, Object {
bytes.length = (int)read;
body.append_buffer(new Soup.Buffer.take(bytes));
}
#endif
private async void upload(FileTransfer file_transfer, HttpFileSendData file_send_data, FileMeta file_meta) throws FileSendError {
Xmpp.XmppStream? stream = stream_interactor.get_stream(file_transfer.account);
if (stream == null) return;
Soup.Message message = new Soup.Message("PUT", file_send_data.url_up);
message.request_headers.set_content_type(file_meta.mime_type, null);
message.request_headers.set_content_length(file_meta.size);
var session = new Soup.Session();
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
var put_message = new Soup.Message("PUT", file_send_data.url_up);
#if SOUP_3
put_message.set_request_body(file_meta.mime_type, file_transfer.input_stream, (ssize_t) file_meta.size);
#else
put_message.request_headers.set_content_type(file_meta.mime_type, null);
put_message.request_headers.set_content_length(file_meta.size);
put_message.request_body.set_accumulate(false);
put_message.wrote_headers.connect(() => transfer_more_bytes(file_transfer.input_stream, put_message.request_body));
put_message.wrote_chunk.connect(() => transfer_more_bytes(file_transfer.input_stream, put_message.request_body));
#endif
foreach (var entry in file_send_data.headers.entries) {
message.request_headers.append(entry.key, entry.value);
put_message.request_headers.append(entry.key, entry.value);
}
message.request_body.set_accumulate(false);
message.wrote_headers.connect(() => transfer_more_bytes(file_transfer.input_stream, message.request_body));
message.wrote_chunk.connect(() => transfer_more_bytes(file_transfer.input_stream, message.request_body));
Soup.Session session = new Soup.Session();
try {
yield session.send_async(message);
if (message.status_code < 200 || message.status_code >= 300) {
throw new FileSendError.UPLOAD_FAILED("HTTP status code %s".printf(message.status_code.to_string()));
#if SOUP_3
yield session.send_async(put_message, GLib.Priority.LOW, file_transfer.cancellable);
#else
yield session.send_async(put_message, file_transfer.cancellable);
#endif
if (put_message.status_code < 200 || put_message.status_code >= 300) {
throw new FileSendError.UPLOAD_FAILED("HTTP status code %s".printf(put_message.status_code.to_string()));
}
} catch (Error e) {
throw new FileSendError.UPLOAD_FAILED("HTTP upload error: %s".printf(e.message));

View file

@ -278,7 +278,6 @@
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="margin">10</property>
<child>
<object class="GtkImage" id="qrcode_image">
<property name="visible">True</property>

View file

@ -38,7 +38,7 @@ public class OmemoFileEncryptor : Dino.FileEncryptor, Object {
omemo_http_file_meta.iv = iv;
omemo_http_file_meta.key = key;
omemo_http_file_meta.size = file_transfer.size + 16;
omemo_http_file_meta.mime_type = "omemo";
omemo_http_file_meta.mime_type = "application/octet-stream";
file_transfer.input_stream = new ConverterInputStream(file_transfer.input_stream, new SymmetricCipherEncrypter((owned) cipher, 16));
} catch (Crypto.Error error) {
throw new FileSendError.ENCRYPTION_FAILED("OMEMO file encryption error: %s".printf(error.message));

View file

@ -92,20 +92,23 @@ public class ContactDetailsDialog : Gtk.Dialog {
copy_button.clicked.connect(() => {Clipboard.get_default(get_display()).set_text(fingerprint, fingerprint.length);});
int sid = plugin.db.identity.row_with(plugin.db.identity.account_id, account.id)[plugin.db.identity.device_id];
Pixbuf qr_pixbuf = new QRcode(@"xmpp:$(account.bare_jid)?omemo-sid-$(sid)=$(fingerprint)", 2).to_pixbuf();
qr_pixbuf = qr_pixbuf.scale_simple(150, 150, InterpType.NEAREST);
var iri_query = @"omemo-sid-$(sid)=$(fingerprint)";
#if GLIB_2_66 && VALA_0_50
string iri = GLib.Uri.join(UriFlags.NONE, "xmpp", null, null, 0, jid.to_string(), iri_query, null);
#else
var iri_path_seg = escape_for_iri_path_segment(jid.to_string());
var iri = @"xmpp:$(iri_path_seg)?$(iri_query)";
#endif
Pixbuf pixbuf = new Pixbuf(
qr_pixbuf.colorspace,
qr_pixbuf.has_alpha,
qr_pixbuf.bits_per_sample,
170,
170
);
pixbuf.fill(uint32.MAX);
qr_pixbuf.copy_area(0, 0, 150, 150, pixbuf, 10, 10);
const int QUIET_ZONE_MODULES = 4; // MUST be at least 4
const int MODULE_SIZE_PX = 4; // arbitrary
var qr_pixbuf = new QRcode(iri, 2)
.to_pixbuf(MODULE_SIZE_PX * qrcode_image.scale_factor);
qrcode_image.set_from_surface(
Gdk.cairo_surface_create_from_pixbuf(qr_pixbuf,0,get_window()));
qrcode_image.margin = QUIET_ZONE_MODULES*MODULE_SIZE_PX;
qrcode_popover.get_style_context().add_class("qrcode-container");
qrcode_image.set_from_pixbuf(pixbuf);
show_qrcode_button.clicked.connect(qrcode_popover.popup);
}
@ -130,6 +133,14 @@ public class ContactDetailsDialog : Gtk.Dialog {
fetch_unknown_bundles();
}
private static string escape_for_iri_path_segment(string s) {
// from RFC 3986, 2.2. Reserved Characters:
string SUB_DELIMS = "!$&'()*+,;=";
// from RFC 3986, 3.3. Path (pchar without unreserved and pct-encoded):
string ALLOWED_RESERVED_CHARS = SUB_DELIMS + ":@";
return GLib.Uri.escape_string(s, ALLOWED_RESERVED_CHARS, true);
}
private void fetch_unknown_bundles() {
Dino.Application app = Application.get_default() as Dino.Application;
XmppStream? stream = app.stream_interactor.get_stream(account);

View file

@ -36,15 +36,47 @@ namespace Qrencode {
[CCode (cname = "QRcode_encodeString")]
public QRcode (string str, int version = 0, ECLevel level = ECLevel.L, EncodeMode hint = EncodeMode.EIGHT_BIT, bool casesensitive = true);
public Pixbuf to_pixbuf() {
uint8[] bitmap = new uint8[3*width*width];
for (int i = 0; i < width*width; i++) {
uint8 color = (data[i] & 1) == 1 ? 0 : 255;
bitmap[i*3] = color;
bitmap[i*3+1] = color;
bitmap[i*3+2] = color;
public Pixbuf to_pixbuf(int module_size) {
GLib.assert(module_size > 0);
var dst_width = width*module_size;
var dst_data = new uint8[dst_width*dst_width*3];
expand_and_upsample(data,width,width, dst_data,dst_width,dst_width);
return new Pixbuf.from_data(dst_data,
Colorspace.RGB, false, 8, dst_width, dst_width, dst_width*3);
}
/** Does 2D nearest-neighbor upsampling of an array of single-byte
* samples, while expanding the least significant bit of each sample
* to three 0-or-255 bytes.
*/
private void expand_and_upsample(
uint8[] src, uint src_w, uint src_h,
uint8[] dst, uint dst_w, uint dst_h) {
GLib.assert(dst_w % src_w == 0);
GLib.assert(dst_h % src_h == 0);
var scale_x = dst_w/src_w,
scale_y = dst_h/src_h;
/* Doing the iteration in the order of destination samples for
* improved cache-friendliness (dst is 48 times larger than src in
* the typical case of scaling by 4x4).
* The choice of multiple nested loops over a single one is for
* avoiding a ton of divisions by non-constants.
*/
for (uint src_y = 0; src_y < src_h; ++src_y) {
for (uint repeat_y = 0; repeat_y < scale_y; ++repeat_y) {
var dst_y = src_y*scale_y + repeat_y;
for (uint src_x = 0; src_x < src_w; ++src_x) {
uint8 value = (src[src_y*src_w + src_x] & 1)==1 ? 0:255;
for (uint repeat_x = 0; repeat_x < scale_x; ++repeat_x){
var dst_x = src_x*scale_x + repeat_x;
var dst_idx = dst_y*dst_w + dst_x;
dst[dst_idx*3+0] = value;
dst[dst_idx*3+1] = value;
dst[dst_idx*3+2] = value;
}
}
}
}
return new Pixbuf.from_data(bitmap, Colorspace.RGB, false, 8, width, width, width*3);
}
}
}

View file

@ -354,6 +354,7 @@ public class Dino.Plugins.Rtp.Device : MediaDevice, Object {
int best_height = 0;
for (int i = 0; i < device.caps.get_size(); i++) {
unowned Gst.Structure? that = device.caps.get_structure(i);
Value? best_fraction_now = null;
if (!that.has_name("video/x-raw")) continue;
int num = 0, den = 0, width = 0, height = 0;
if (!that.has_field("framerate")) continue;
@ -369,7 +370,7 @@ public class Dino.Plugins.Rtp.Device : MediaDevice, Object {
int fps = den > 0 ? (num/den) : 0;
int in_fps = in_den > 0 ? (in_num/in_den) : 0;
if (in_fps > fps) {
best_fraction = fraction;
best_fraction_now = fraction;
num = in_num;
den = in_den;
}
@ -386,6 +387,7 @@ public class Dino.Plugins.Rtp.Device : MediaDevice, Object {
best_width = width;
best_height = height;
best_index = i;
best_fraction = best_fraction_now;
}
}
Gst.Caps res = caps_copy_nth(device.caps, best_index);

View file

@ -384,9 +384,27 @@ public class Dino.Plugins.Rtp.Plugin : RootInterface, VideoCallPlugin, Object {
int fps = 0;
for (int i = 0; i < device.device.caps.get_size(); i++) {
unowned Gst.Structure structure = device.device.caps.get_structure(i);
int num = 0, den = 0;
if (structure.has_field("framerate") && structure.get_fraction("framerate", out num, out den)) fps = int.max(fps, num / den);
if (structure.has_field("framerate")) {
Value framerate = structure.get_value("framerate");
if (framerate.type() == typeof(Gst.Fraction)) {
int num = Gst.Value.get_fraction_numerator(framerate);
int den = Gst.Value.get_fraction_denominator(framerate);
fps = int.max(fps, num / den);
} else if (framerate.type() == typeof(Gst.ValueList)) {
for(uint j = 0; j < Gst.ValueList.get_size(framerate); j++) {
Value fraction = Gst.ValueList.get_value(framerate, j);
int num = Gst.Value.get_fraction_numerator(fraction);
int den = Gst.Value.get_fraction_denominator(fraction);
fps = int.max(fps, num / den);
}
} else {
debug("Unknown type for framerate %s on device %s", framerate.type_name(), device.display_name);
}
}
}
debug("Max framerate for device %s: %d", device.display_name, fps);
return fps;
}

View file

@ -48,7 +48,7 @@ public abstract class Gee.TestCase : Object {
}
public GLib.TestSuite get_suite () {
return this.suite;
return (owned) this.suite;
}
private class Adaptor {

View file

@ -56,7 +56,7 @@ public abstract class Gee.TestCase : Object {
}
public GLib.TestSuite get_suite () {
return this.suite;
return (owned) this.suite;
}
}